Almost always, if you can choose between the two, choose `const`. It’s pretty
rare that you actually want a memory location associated with your constant,
-and using a const allows for optimizations like constant propagation not only
+and using a `const` allows for optimizations like constant propagation not only
in your crate but downstream crates.
use ty::relate::{Relate, RelateResult, TypeRelation};
use traits::{self, PredicateObligations, ProjectionMode};
use rustc_data_structures::unify::{self, UnificationTable};
-use std::cell::{RefCell, Ref};
+use std::cell::{Cell, RefCell, Ref};
use std::fmt;
use syntax::ast;
use syntax::codemap;
// documentation for `ProjectionMode`.
projection_mode: ProjectionMode,
+ // When an error occurs, we want to avoid reporting "derived"
+ // errors that are due to this original failure. Normally, we
+ // handle this with the `err_count_on_creation` count, which
+ // basically just tracks how many errors were reported when we
+ // started type-checking a fn and checks to see if any new errors
+ // have been reported since then. Not great, but it works.
+ //
+ // However, when errors originated in other passes -- notably
+ // resolve -- this heuristic breaks down. Therefore, we have this
+ // auxiliary flag that one can set whenever one creates a
+ // type-error that is due to an error in a prior pass.
+ //
+ // Don't read this flag directly, call `is_tainted_by_errors()`
+ // and `set_tainted_by_errors()`.
+ tainted_by_errors_flag: Cell<bool>,
+
+ // Track how many errors were reported when this infcx is created.
+ // If the number of errors increases, that's also a sign (line
+ // `tained_by_errors`) to avoid reporting certain kinds of errors.
err_count_on_creation: usize,
}
reported_trait_errors: RefCell::new(FnvHashSet()),
normalize: false,
projection_mode: projection_mode,
+ tainted_by_errors_flag: Cell::new(false),
err_count_on_creation: tcx.sess.err_count()
}
}
.map(|method| resolve_ty(method.ty)))
}
- pub fn errors_since_creation(&self) -> bool {
- self.tcx.sess.err_count() - self.err_count_on_creation != 0
+ /// True if errors have been reported since this infcx was
+ /// created. This is sometimes used as a heuristic to skip
+ /// reporting errors that often occur as a result of earlier
+ /// errors, but where it's hard to be 100% sure (e.g., unresolved
+ /// inference variables, regionck errors).
+ pub fn is_tainted_by_errors(&self) -> bool {
+ debug!("is_tainted_by_errors(err_count={}, err_count_on_creation={}, \
+ tainted_by_errors_flag={})",
+ self.tcx.sess.err_count(),
+ self.err_count_on_creation,
+ self.tainted_by_errors_flag.get());
+
+ if self.tcx.sess.err_count() > self.err_count_on_creation {
+ return true; // errors reported since this infcx was made
+ }
+ self.tainted_by_errors_flag.get()
+ }
+
+ /// Set the "tainted by errors" flag to true. We call this when we
+ /// observe an error from a prior pass.
+ pub fn set_tainted_by_errors(&self) {
+ debug!("set_tainted_by_errors()");
+ self.tainted_by_errors_flag.set(true)
}
pub fn node_type(&self, id: ast::NodeId) -> Ty<'tcx> {
match self.tables.borrow().node_types.get(&id) {
Some(&t) => t,
// FIXME
- None if self.errors_since_creation() =>
+ None if self.is_tainted_by_errors() =>
self.tcx.types.err,
None => {
bug!("no type for node {}: {} in fcx",
free_regions: &FreeRegionMap,
subject_node_id: ast::NodeId) {
let errors = self.region_vars.resolve_regions(free_regions, subject_node_id);
- if !self.errors_since_creation() {
+ if !self.is_tainted_by_errors() {
// As a heuristic, just skip reporting region errors
// altogether if other errors have been reported while
// this infcx was in use. This is totally hokey but
}
(&ty::TyError, _) | (_, &ty::TyError) => {
+ infcx.set_tainted_by_errors();
Ok(self.tcx().types.err)
}
predicate,
obligation);
+ // Ambiguity errors are often caused as fallout from earlier
+ // errors. So just ignore them if this infcx is tainted.
+ if infcx.is_tainted_by_errors() {
+ return;
+ }
+
match predicate {
ty::Predicate::Trait(ref data) => {
let trait_ref = data.to_poly_trait_ref();
}).unwrap_or((10, 7));
TargetOptions {
- // OSX has -dead_strip, which doesn't rely on ffunction_sections
+ // OSX has -dead_strip, which doesn't rely on function_sections
function_sections: false,
- linker: "cc".to_string(),
dynamic_linking: true,
executables: true,
is_like_osx: true,
pub fn target() -> Target {
let mut base = super::android_base::opts();
- base.features = "+v7".to_string();
+ base.features = "+v7,+vfp3,+d16".to_string();
Target {
llvm_target: "arm-linux-androideabi".to_string(),
pub fn opts() -> TargetOptions {
TargetOptions {
- linker: "cc".to_string(),
dynamic_linking: true,
executables: true,
linker_is_gnu: true,
pub fn opts() -> TargetOptions {
TargetOptions {
- linker: "cc".to_string(),
dynamic_linking: true,
executables: true,
linker_is_gnu: true,
pub fn opts() -> TargetOptions {
TargetOptions {
- linker: "cc".to_string(),
dynamic_linking: true,
executables: true,
linker_is_gnu: true,
pub fn opts() -> TargetOptions {
TargetOptions {
- linker: "cc".to_string(),
dynamic_linking: true,
executables: true,
linker_is_gnu: true,
pub fn opts() -> TargetOptions {
TargetOptions {
- linker: "cc".to_string(),
dynamic_linking: true,
executables: true,
linker_is_gnu: true,
pub fn opts() -> TargetOptions {
TargetOptions {
- linker: "cc".to_string(),
dynamic_linking: true,
executables: true,
has_rpath: true,
_trait_ref: ty::TraitRef<'tcx>,
_item_name: ast::Name)
-> Ty<'tcx>;
+
+ /// Invoked when we encounter an error from some prior pass
+ /// (e.g. resolve) that is translated into a ty-error. This is
+ /// used to help suppress derived errors typeck might otherwise
+ /// report.
+ fn set_tainted_by_errors(&self);
}
pub fn ast_region_to_region(tcx: &TyCtxt, lifetime: &hir::Lifetime)
prim_ty_to_ty(tcx, base_segments, prim_ty)
}
Def::Err => {
+ this.set_tainted_by_errors();
return this.tcx().types.err;
}
_ => {
let self_ty = fcx.to_ty(&qself.ty);
let path_res = if let Some(&d) = tcx.def_map.borrow().get(&pat.id) {
if d.base_def == Def::Err {
+ fcx.infcx().set_tainted_by_errors();
fcx.write_error(pat.id);
return;
}
let path_res = match tcx.def_map.borrow().get(&pat.id) {
Some(&path_res) if path_res.base_def != Def::Err => path_res,
_ => {
+ fcx.infcx().set_tainted_by_errors();
fcx.write_error(pat.id);
if let Some(subpats) = subpats {
use lint;
use hir::def_id::DefId;
+use rustc::hir;
+use rustc::traits;
use rustc::ty::{self, Ty, TypeFoldable};
use rustc::ty::cast::{CastKind, CastTy};
-use syntax::codemap::Span;
-use rustc::hir;
use syntax::ast;
-
+use syntax::codemap::Span;
+use util::common::ErrorReported;
/// Reifies a cast check to be checked once we have full type information for
/// a function context.
expr: &'tcx hir::Expr,
expr_ty: Ty<'tcx>,
cast_ty: Ty<'tcx>,
+ cast_span: Span,
span: Span,
}
}
impl<'tcx> CastCheck<'tcx> {
- pub fn new(expr: &'tcx hir::Expr, expr_ty: Ty<'tcx>, cast_ty: Ty<'tcx>, span: Span)
- -> CastCheck<'tcx> {
- CastCheck {
+ pub fn new<'a>(fcx: &FnCtxt<'a, 'tcx>,
+ expr: &'tcx hir::Expr,
+ expr_ty: Ty<'tcx>,
+ cast_ty: Ty<'tcx>,
+ cast_span: Span,
+ span: Span)
+ -> Result<CastCheck<'tcx>, ErrorReported> {
+ let check = CastCheck {
expr: expr,
expr_ty: expr_ty,
cast_ty: cast_ty,
+ cast_span: cast_span,
span: span,
+ };
+
+ // For better error messages, check for some obviously unsized
+ // cases now. We do a more thorough check at the end, once
+ // inference is more completely known.
+ match cast_ty.sty {
+ ty::TyTrait(..) | ty::TySlice(..) => {
+ check.report_cast_to_unsized_type(fcx);
+ Err(ErrorReported)
+ }
+ _ => {
+ Ok(check)
+ }
}
}
- fn report_cast_error<'a>(&self, fcx: &FnCtxt<'a, 'tcx>,
+ fn report_cast_error<'a>(&self,
+ fcx: &FnCtxt<'a, 'tcx>,
e: CastError) {
match e {
CastError::NeedViaPtr |
}
}
+ fn report_cast_to_unsized_type<'a>(&self,
+ fcx: &FnCtxt<'a, 'tcx>) {
+ if
+ self.cast_ty.references_error() ||
+ self.expr_ty.references_error()
+ {
+ return;
+ }
+
+ let tstr = fcx.infcx().ty_to_string(self.cast_ty);
+ let mut err = fcx.type_error_struct(self.span, |actual| {
+ format!("cast to unsized type: `{}` as `{}`", actual, tstr)
+ }, self.expr_ty, None);
+ match self.expr_ty.sty {
+ ty::TyRef(_, ty::TypeAndMut { mutbl: mt, .. }) => {
+ let mtstr = match mt {
+ hir::MutMutable => "mut ",
+ hir::MutImmutable => ""
+ };
+ if self.cast_ty.is_trait() {
+ match fcx.tcx().sess.codemap().span_to_snippet(self.cast_span) {
+ Ok(s) => {
+ err.span_suggestion(self.cast_span,
+ "try casting to a reference instead:",
+ format!("&{}{}", mtstr, s));
+ },
+ Err(_) =>
+ span_help!(err, self.cast_span,
+ "did you mean `&{}{}`?", mtstr, tstr),
+ }
+ } else {
+ span_help!(err, self.span,
+ "consider using an implicit coercion to `&{}{}` instead",
+ mtstr, tstr);
+ }
+ }
+ ty::TyBox(..) => {
+ match fcx.tcx().sess.codemap().span_to_snippet(self.cast_span) {
+ Ok(s) => {
+ err.span_suggestion(self.cast_span,
+ "try casting to a `Box` instead:",
+ format!("Box<{}>", s));
+ },
+ Err(_) =>
+ span_help!(err, self.cast_span, "did you mean `Box<{}>`?", tstr),
+ }
+ }
+ _ => {
+ span_help!(err, self.expr.span,
+ "consider using a box or reference as appropriate");
+ }
+ }
+ err.emit();
+ }
+
fn trivial_cast_lint<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) {
let t_cast = self.cast_ty;
let t_expr = self.expr_ty;
debug!("check_cast({}, {:?} as {:?})", self.expr.id, self.expr_ty,
self.cast_ty);
- if self.expr_ty.references_error() || self.cast_ty.references_error() {
+ if !fcx.type_is_known_to_be_sized(self.cast_ty, self.span) {
+ self.report_cast_to_unsized_type(fcx);
+ } else if self.expr_ty.references_error() || self.cast_ty.references_error() {
// No sense in giving duplicate error messages
} else if self.try_coercion_cast(fcx) {
self.trivial_cast_lint(fcx);
}
}
+
+impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+ fn type_is_known_to_be_sized(&self,
+ ty: Ty<'tcx>,
+ span: Span)
+ -> bool
+ {
+ traits::type_known_to_meet_builtin_bound(self.infcx(),
+ ty,
+ ty::BoundSized,
+ span)
+ }
+}
+
}
}
-fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
- span: Span,
- t_span: Span,
- e_span: Span,
- t_cast: Ty<'tcx>,
- t_expr: Ty<'tcx>,
- id: ast::NodeId) {
- if t_cast.references_error() || t_expr.references_error() {
- return;
- }
- let tstr = fcx.infcx().ty_to_string(t_cast);
- let mut err = fcx.type_error_struct(span, |actual| {
- format!("cast to unsized type: `{}` as `{}`", actual, tstr)
- }, t_expr, None);
- match t_expr.sty {
- ty::TyRef(_, ty::TypeAndMut { mutbl: mt, .. }) => {
- let mtstr = match mt {
- hir::MutMutable => "mut ",
- hir::MutImmutable => ""
- };
- if t_cast.is_trait() {
- match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
- Ok(s) => {
- err.span_suggestion(t_span,
- "try casting to a reference instead:",
- format!("&{}{}", mtstr, s));
- },
- Err(_) =>
- span_help!(err, t_span,
- "did you mean `&{}{}`?", mtstr, tstr),
- }
- } else {
- span_help!(err, span,
- "consider using an implicit coercion to `&{}{}` instead",
- mtstr, tstr);
- }
- }
- ty::TyBox(..) => {
- match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
- Ok(s) => {
- err.span_suggestion(t_span,
- "try casting to a `Box` instead:",
- format!("Box<{}>", s));
- },
- Err(_) =>
- span_help!(err, t_span, "did you mean `Box<{}>`?", tstr),
- }
- }
- _ => {
- span_help!(err, e_span,
- "consider using a box or reference as appropriate");
- }
- }
- err.emit();
- fcx.write_error(id);
-}
-
-
impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
fn tcx(&self) -> &TyCtxt<'tcx> { self.ccx.tcx }
{
self.normalize_associated_type(span, trait_ref, item_name)
}
+
+ fn set_tainted_by_errors(&self) {
+ self.infcx().set_tainted_by_errors()
+ }
}
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
}
- pub fn type_is_known_to_be_sized(&self,
- ty: Ty<'tcx>,
- span: Span)
- -> bool
- {
- traits::type_known_to_meet_builtin_bound(self.infcx(),
- ty,
- ty::BoundSized,
- span)
- }
-
pub fn register_builtin_bound(&self,
ty: Ty<'tcx>,
builtin_bound: ty::BuiltinBound,
fn default_type_parameters(&self) {
use rustc::ty::error::UnconstrainedNumeric::Neither;
use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
+
+ // Defaulting inference variables becomes very dubious if we have
+ // encountered type-checking errors. Therefore, if we think we saw
+ // some errors in this function, just resolve all uninstanted type
+ // varibles to TyError.
+ if self.infcx().is_tainted_by_errors() {
+ for ty in &self.infcx().unsolved_variables() {
+ if let ty::TyInfer(_) = self.infcx().shallow_resolve(ty).sty {
+ debug!("default_type_parameters: defaulting `{:?}` to error", ty);
+ demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.err);
+ }
+ }
+ return;
+ }
+
for ty in &self.infcx().unsolved_variables() {
let resolved = self.infcx().resolve_type_vars_if_possible(ty);
if self.infcx().type_var_diverges(resolved) {
+ debug!("default_type_parameters: defaulting `{:?}` to `()` because it diverges",
+ resolved);
demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
} else {
match self.infcx().type_is_unconstrained_numeric(resolved) {
UnconstrainedInt => {
+ debug!("default_type_parameters: defaulting `{:?}` to `i32`",
+ resolved);
demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
},
UnconstrainedFloat => {
+ debug!("default_type_parameters: defaulting `{:?}` to `f32`",
+ resolved);
demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
}
Neither => { }
// Find the relevant variant
let def = lookup_full_def(tcx, path.span, expr.id);
if def == Def::Err {
+ fcx.infcx().set_tainted_by_errors();
check_struct_fields_on_error(fcx, expr.id, fields, base_expr);
return;
}
expr.span,
id);
} else {
+ fcx.infcx().set_tainted_by_errors();
fcx.write_ty(id, fcx.tcx().types.err);
}
}
// Find the type of `e`. Supply hints based on the type we are casting to,
// if appropriate.
let t_cast = fcx.to_ty(t);
- let t_cast = structurally_resolved_type(fcx, expr.span, t_cast);
+ let t_cast = fcx.infcx().resolve_type_vars_if_possible(&t_cast);
check_expr_with_expectation(fcx, e, ExpectCastableToType(t_cast));
let t_expr = fcx.expr_ty(e);
let t_cast = fcx.infcx().resolve_type_vars_if_possible(&t_cast);
// Eagerly check for some obvious errors.
if t_expr.references_error() || t_cast.references_error() {
fcx.write_error(id);
- } else if !fcx.type_is_known_to_be_sized(t_cast, expr.span) {
- report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_cast, t_expr, id);
} else {
// Write a type for the whole expression, assuming everything is going
// to work out Ok.
// Defer other checks until we're done type checking.
let mut deferred_cast_checks = fcx.inh.deferred_cast_checks.borrow_mut();
- let cast_check = cast::CastCheck::new(e, t_expr, t_cast, expr.span);
- deferred_cast_checks.push(cast_check);
+ match cast::CastCheck::new(fcx, e, t_expr, t_cast, t.span, expr.span) {
+ Ok(cast_check) => {
+ deferred_cast_checks.push(cast_check);
+ }
+ Err(ErrorReported) => {
+ fcx.write_error(id);
+ }
+ }
}
}
hir::ExprType(ref e, ref t) => {
Def::ForeignMod(..) |
Def::Local(..) |
Def::Label(..) |
- Def::Upvar(..) |
+ Def::Upvar(..) => {
+ segment_spaces = vec![None; segments.len()];
+ }
+
Def::Err => {
+ fcx.infcx().set_tainted_by_errors();
segment_spaces = vec![None; segments.len()];
}
}
// If not, error.
if alternative.is_ty_var() || alternative.references_error() {
- fcx.type_error_message(sp, |_actual| {
- "the type of this value must be known in this context".to_string()
- }, ty, None);
+ if !fcx.infcx().is_tainted_by_errors() {
+ fcx.type_error_message(sp, |_actual| {
+ "the type of this value must be known in this context".to_string()
+ }, ty, None);
+ }
demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
ty = fcx.tcx().types.err;
} else {
use rustc::infer::{self, InferCtxt, TypeOrigin, new_infer_ctxt};
use std::cell::RefCell;
use std::rc::Rc;
-use syntax::ast;
use syntax::codemap::Span;
-use syntax::errors::DiagnosticBuilder;
use util::nodemap::{DefIdMap, FnvHashMap};
use rustc::dep_graph::DepNode;
use rustc::hir::map as hir_map;
err.emit();
}
-// Factored out into helper because the error cannot be defined in multiple locations.
-pub fn report_duplicate_item<'tcx>(tcx: &TyCtxt<'tcx>, sp: Span, name: ast::Name)
- -> DiagnosticBuilder<'tcx>
-{
- struct_span_err!(tcx.sess, sp, E0201, "duplicate definitions with name `{}`:", name)
-}
-
pub fn check_coherence(crate_context: &CrateCtxt) {
let _task = crate_context.tcx.dep_graph.in_task(DepNode::Coherence);
let infcx = new_infer_ctxt(crate_context.tcx,
use hir::def::Def;
use hir::def_id::DefId;
use constrained_type_params as ctp;
-use coherence;
use middle::lang_items::SizedTraitLangItem;
use middle::resolve_lifetime;
use middle::const_val::ConstVal;
use rustc::dep_graph::DepNode;
use rustc::hir::map as hir_map;
use util::common::{ErrorReported, MemoizationMap};
-use util::nodemap::{FnvHashMap, FnvHashSet};
+use util::nodemap::FnvHashMap;
use write_ty_to_tcx;
use rustc_const_math::ConstInt;
use std::cell::RefCell;
use std::collections::HashSet;
+use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::rc::Rc;
use syntax::abi;
{
self.tcx().mk_projection(trait_ref, item_name)
}
+
+ fn set_tainted_by_errors(&self) {
+ // no obvious place to track this, just let it go
+ }
}
/// Interface used to find the bounds on a type parameter from within
// Convert all the associated consts.
// Also, check if there are any duplicate associated items
- let mut seen_type_items = FnvHashSet();
- let mut seen_value_items = FnvHashSet();
+ let mut seen_type_items = FnvHashMap();
+ let mut seen_value_items = FnvHashMap();
for impl_item in impl_items {
let seen_items = match impl_item.node {
hir::ImplItemKind::Type(_) => &mut seen_type_items,
_ => &mut seen_value_items,
};
- if !seen_items.insert(impl_item.name) {
- coherence::report_duplicate_item(tcx, impl_item.span, impl_item.name).emit();
+ match seen_items.entry(impl_item.name) {
+ Occupied(entry) => {
+ let mut err = struct_span_err!(tcx.sess, impl_item.span, E0201,
+ "duplicate definitions with name `{}`:",
+ impl_item.name);
+ span_note!(&mut err, *entry.get(),
+ "previous definition of `{}` here",
+ impl_item.name);
+ err.emit();
+ }
+ Vacant(entry) => {
+ entry.insert(impl_item.span);
+ }
}
if let hir::ImplItemKind::Const(ref ty, _) = impl_item.node {
let inner = match def {
Def::Trait(did) => {
record_extern_fqn(cx, did, clean::TypeTrait);
+ ret.extend(build_impls(cx, tcx, did));
clean::TraitItem(build_external_trait(cx, tcx, did))
}
Def::Fn(did) => {
// Primarily, the impls will be used to populate the documentation for this
// type being inlined, but impls can also be used when generating
// documentation for primitives (no way to find those specifically).
- if !cx.all_crate_impls.borrow_mut().contains_key(&did.krate) {
- let mut impls = Vec::new();
+ if cx.populated_crate_impls.borrow_mut().insert(did.krate) {
for item in tcx.sess.cstore.crate_top_level_items(did.krate) {
populate_impls(cx, tcx, item.def, &mut impls);
}
- cx.all_crate_impls.borrow_mut().insert(did.krate, impls);
fn populate_impls(cx: &DocContext, tcx: &TyCtxt,
def: cstore::DefLike,
}
}
- let mut candidates = cx.all_crate_impls.borrow_mut();
- let candidates = candidates.get_mut(&did.krate).unwrap();
- for i in (0..candidates.len()).rev() {
- let remove = match candidates[i].inner {
- clean::ImplItem(ref i) => {
- i.for_.def_id() == Some(did) || i.for_.primitive_type().is_some()
- }
- _ => continue,
- };
- if remove {
- impls.push(candidates.swap_remove(i));
- }
- }
-
- return impls;
+ impls
}
pub fn build_impl(cx: &DocContext,
use syntax::parse::token;
use std::cell::{RefCell, Cell};
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
use std::rc::Rc;
use visit_ast::RustdocVisitor;
pub map: &'a hir_map::Map<'tcx>,
pub maybe_typed: MaybeTyped<'a, 'tcx>,
pub input: Input,
- pub all_crate_impls: RefCell<HashMap<ast::CrateNum, Vec<clean::Item>>>,
+ pub populated_crate_impls: RefCell<HashSet<ast::CrateNum>>,
pub deref_trait_did: Cell<Option<DefId>>,
// Note that external items for which `doc(hidden)` applies to are shown as
// non-reachable while local items aren't. This is because we're reusing
map: &tcx.map,
maybe_typed: Typed(tcx),
input: input,
- all_crate_impls: RefCell::new(HashMap::new()),
+ populated_crate_impls: RefCell::new(HashSet::new()),
deref_trait_did: Cell::new(None),
access_levels: RefCell::new(access_levels),
external_traits: RefCell::new(HashMap::new()),
pub fn href(did: DefId) -> Option<(String, ItemType, Vec<String>)> {
let cache = cache();
+ if !did.is_local() && !cache.access_levels.is_doc_reachable(did) {
+ return None
+ }
+
let loc = CURRENT_LOCATION_KEY.with(|l| l.borrow().clone());
let &(ref fqp, shortty) = match cache.paths.get(&did) {
Some(p) => p,
None => return None,
};
+
let mut url = if did.is_local() || cache.inlined.contains(&did) {
repeat("../").take(loc.len()).collect::<String>()
} else {
- if !cache.access_levels.is_doc_reachable(did) {
- return None
- }
match cache.extern_locations[&did.krate] {
(_, render::Remote(ref s)) => s.to_string(),
(_, render::Local) => repeat("../").take(loc.len()).collect(),
}
fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Result {
- if let Some(s) = short_stability(item, cx, true) {
- write!(w, "<div class='stability'>{}</div>", s)?;
+ for stability in short_stability(item, cx, true) {
+ write!(w, "<div class='stability'>{}</div>", stability)?;
}
if let Some(s) = item.doc_value() {
write!(w, "<div class='docblock'>{}</div>", Markdown(s))?;
_ => {
if myitem.name.is_none() { continue }
- let stab_docs = if let Some(s) = short_stability(myitem, cx, false) {
- format!("[{}]", s)
+
+ let stabilities = short_stability(myitem, cx, false);
+
+ let stab_docs = if !stabilities.is_empty() {
+ stabilities.iter()
+ .map(|s| format!("[{}]", s))
+ .collect::<Vec<_>>()
+ .as_slice()
+ .join(" ")
} else {
String::new()
};
write!(w, "</table>")
}
-fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Option<String> {
- item.stability.as_ref().and_then(|stab| {
+fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<String> {
+ let mut stability = vec![];
+
+ if let Some(stab) = item.stability.as_ref() {
let reason = if show_reason && !stab.reason.is_empty() {
format!(": {}", stab.reason)
} else {
String::new()
};
- let text = if !stab.deprecated_since.is_empty() {
+ if !stab.deprecated_since.is_empty() {
let since = if show_reason {
format!(" since {}", Escape(&stab.deprecated_since))
} else {
String::new()
};
- format!("Deprecated{}{}", since, Markdown(&reason))
- } else if stab.level == stability::Unstable {
+ let text = format!("Deprecated{}{}", since, Markdown(&reason));
+ stability.push(format!("<em class='stab deprecated'>{}</em>", text))
+ };
+
+ if stab.level == stability::Unstable {
let unstable_extra = if show_reason {
match (!stab.feature.is_empty(), &cx.shared.issue_tracker_base_url, stab.issue) {
(true, &Some(ref tracker_url), Some(issue_no)) if issue_no > 0 =>
} else {
String::new()
};
- format!("Unstable{}{}", unstable_extra, Markdown(&reason))
+ let text = format!("Unstable{}{}", unstable_extra, Markdown(&reason));
+ stability.push(format!("<em class='stab unstable'>{}</em>", text))
+ };
+ } else if let Some(depr) = item.deprecation.as_ref() {
+ let note = if show_reason && !depr.note.is_empty() {
+ format!(": {}", depr.note)
} else {
- return None
+ String::new()
+ };
+ let since = if show_reason && !depr.since.is_empty() {
+ format!(" since {}", Escape(&depr.since))
+ } else {
+ String::new()
};
- Some(format!("<em class='stab {}'>{}</em>",
- item.stability_class(), text))
- }).or_else(|| {
- item.deprecation.as_ref().and_then(|depr| {
- let note = if show_reason && !depr.note.is_empty() {
- format!(": {}", depr.note)
- } else {
- String::new()
- };
- let since = if show_reason && !depr.since.is_empty() {
- format!(" since {}", Escape(&depr.since))
- } else {
- String::new()
- };
- let text = format!("Deprecated{}{}", since, Markdown(¬e));
- Some(format!("<em class='stab deprecated'>{}</em>", text))
- })
- })
+ let text = format!("Deprecated{}{}", since, Markdown(¬e));
+ stability.push(format!("<em class='stab deprecated'>{}</em>", text))
+ }
+
+ stability
}
struct Initializer<'a>(&'a str);
if !is_static || render_static {
let id = derive_id(format!("{}.{}", shortty, name));
write!(w, "<h4 id='{}' class='{}'>", id, shortty)?;
- render_stability_since_raw(w, item.stable_since(), outer_version)?;
write!(w, "<code>")?;
render_assoc_item(w, item, link.anchor(&id))?;
- write!(w, "</code></h4>\n")?;
+ write!(w, "</code>")?;
+ render_stability_since_raw(w, item.stable_since(), outer_version)?;
+ write!(w, "</h4>\n")?;
}
}
clean::TypedefItem(ref tydef, _) => {
$(".method").each(function() {
if ($(this).next().is(".docblock") ||
($(this).next().is(".stability") && $(this).next().next().is(".docblock"))) {
- $(this).children().first().after(toggle.clone());
+ $(this).children().last().after(toggle.clone());
}
});
// except according to those terms.
use std::cell::{RefCell, Cell};
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
use std::env;
use std::ffi::OsString;
use std::io::prelude::*;
maybe_typed: core::NotTyped(&sess),
input: input,
external_traits: RefCell::new(HashMap::new()),
- all_crate_impls: RefCell::new(HashMap::new()),
+ populated_crate_impls: RefCell::new(HashSet::new()),
deref_trait_did: Cell::new(None),
access_levels: Default::default(),
renderinfo: Default::default(),
/// `addr` is an address of the remote host. Anything which implements
/// `ToSocketAddrs` trait can be supplied for the address; see this trait
/// documentation for concrete examples.
+ /// In case `ToSocketAddrs::to_socket_addrs()` returns more than one entry,
+ /// then the first valid and reachable address is used.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
super::each_addr(addr, net_imp::TcpStream::connect).map(TcpStream)
"rustc_bitflags 0.0.0",
"rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0",
+ "rustc_llvm 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
]
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name="bar"]
+
+pub trait Bar {}
+pub struct Foo;
+
+impl<'a> Bar for &'a char {}
+impl Bar for Foo {}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[doc(hidden)]
+pub struct Foo;
+
+pub struct Bar;
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::fmt;
+
+pub trait Bar {}
+
+impl<'a> Bar + 'a {
+ pub fn bar(&self) -> usize { 42 }
+}
+
+impl<'a> fmt::Debug for Bar + 'a {
+ fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
+ Ok(())
+ }
+}
+
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// RFC 401 test extracted into distinct file. This is because some the
+// change to suppress "derived" errors wound up suppressing this error
+// message, since the fallback for `3` doesn't occur.
+
+fn main() {
+ let _ = 3 as bool;
+ //~^ ERROR cannot cast as `bool`
+ //~| HELP compare with zero
+}
let _ = f as *const u8;
//~^ ERROR casting
//~^^ HELP through a usize first
- let _ = 3 as bool;
+ let _ = 3_i32 as bool;
//~^ ERROR cannot cast as `bool`
//~| HELP compare with zero
let _ = E::A as bool;
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we do not see uninformative region-related errors
+// when we get some basic type-checking failure. See #30580.
+
+pub struct Foo { a: u32 }
+pub struct Pass<'a, 'tcx: 'a>(&'a mut &'a (), &'a &'tcx ());
+
+impl<'a, 'tcx> Pass<'a, 'tcx>
+{
+ pub fn tcx(&self) -> &'a &'tcx () { self.1 }
+ fn lol(&mut self, b: &Foo)
+ {
+ b.c; //~ ERROR no field with that name was found
+ self.tcx();
+ }
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for this example from #31997 -- main goal is to
+// emit as minimal and precise an error set as possible. Ideally, we'd
+// only emit the E0433 error below, but right now we emit two.
+
+use std::io::prelude::*;
+// use std::collections::HashMap;
+use std::io;
+
+#[derive(Debug)]
+struct Instance {
+ name: String,
+ start: Option<String>,
+ end: Option<String>,
+}
+
+fn main() {
+ let input = io::stdin();
+ let mut input = input.lock();
+
+ let mut map = HashMap::new();
+ //~^ ERROR E0433
+
+ for line in input.lines() {
+ let line = line.unwrap();
+ println!("process: {}", line);
+ let mut parts = line.splitn(2, ":");
+ let _logfile = parts.next().unwrap();
+ let rest = parts.next().unwrap();
+ let mut parts = line.split(" [-] ");
+
+ let stamp = parts.next().unwrap();
+
+ let rest = parts.next().unwrap();
+ let words = rest.split_whitespace().collect::<Vec<_>>();
+
+ let instance = words.iter().find(|a| a.starts_with("i-")).unwrap();
+ let name = words[1].to_owned();
+ let mut entry = map.entry(instance.to_owned()).or_insert(Instance {
+ name: name,
+ start: None,
+ end: None,
+ });
+
+ if rest.contains("terminating") {
+ assert!(entry.end.is_none());
+ entry.end = Some(stamp.to_string());
+ }
+ if rest.contains("waiting for") {
+ assert!(entry.start.is_none());
+ entry.start = Some(stamp.to_string());
+ }
+
+ }
+
+ println!("{:?}", map);
+}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that the resolve failure does not lead to downstream type errors.
+// See issue #31997.
+
+trait TheTrait { }
+
+fn closure<F, T>(x: F) -> Result<T, ()>
+ where F: FnMut() -> T, T: TheTrait,
+{
+ unimplemented!()
+}
+
+fn foo() -> Result<(), ()> {
+ try!(closure(|| bar(0 as *mut _))); //~ ERROR unresolved name `bar`
+ Ok(())
+}
+
+fn main() { }
// except according to those terms.
struct Foo;
+
impl Foo {
- fn orange(&self){}
- fn orange(&self){} //~ ERROR duplicate definitions
+ fn orange(&self) {} //~ NOTE previous definition of `orange` here
+ fn orange(&self) {} //~ ERROR duplicate definitions with name `orange`
}
fn main() {}
fn iterate<N: Node, G: Graph<N>>(graph: &G) {
for node in graph.iter() { //~ ERROR no method named `iter` found
- node.zomg(); //~ error: the type of this value must be known in this context
+ node.zomg();
}
}
fn akemi(homura: Homura) {
let Some(ref madoka) = Some(homura.kaname()); //~ ERROR no method named `kaname` found
- madoka.clone(); //~ ERROR the type of this value must be known
+ madoka.clone();
}
fn main() { }
fn main() {
for (ref i,) in [].iter() { //~ ERROR mismatched types
i.clone();
- //~^ ERROR: the type of this value must be known in this context
}
}
}
macro_rules! cast {
- ($x:expr) => ($x as ())
- //~^ ERROR non-scalar cast: `i32` as `()`
+ ($x:expr) => ($x as ()) //~ ERROR non-scalar cast
}
fn main() {
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that we do not see uninformative region-related errors
-// when we get some basic type-checking failure. See #30580.
-
-pub struct Foo { a: u32 }
-pub struct Pass<'a, 'tcx: 'a>(&'a mut &'a (), &'a &'tcx ());
-
-impl<'a, 'tcx> Pass<'a, 'tcx>
-{
- pub fn tcx(&self) -> &'a &'tcx () { self.1 }
- fn lol(&mut self, b: &Foo)
- {
- b.c; //~ ERROR no field with that name was found
- self.tcx();
- }
-}
-
-fn main() {}
fn main() {
let p = Point::new(0.0, 0.0);
//~^ ERROR no associated item named `new` found for type `Point` in the current scope
- println!("{}", p.to_string()); //~ ERROR type of this value must be known
+ println!("{}", p.to_string());
}
//~| found `std::option::Option<_>`
//~| expected enum `Whatever`
//~| found enum `std::option::Option`
- field.access(), //~ ERROR the type of this value must be known in this context
+ field.access(),
}
}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that we allow a cast to `_` so long as the target type can be
+// inferred elsewhere.
+
+pub fn main() {
+ let i: *const i32 = 0 as _;
+ assert!(i.is_null());
+}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:rustdoc-hidden.rs
+// build-aux-docs
+// ignore-cross-compile
+
+extern crate rustdoc_hidden;
+
+#[doc(no_inline)]
+pub use rustdoc_hidden::Foo;
+
+// @has inline_hidden/fn.foo.html
+// @!has - '//a/@title' 'Foo'
+pub fn foo(_: Foo) {}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:rustdoc-trait-object-impl.rs
+// build-aux-docs
+// ignore-cross-compile
+
+extern crate rustdoc_trait_object_impl;
+
+// @has issue_32881/trait.Bar.html
+// @has - '//code' "impl<'a> Bar"
+// @has - '//code' "impl<'a> Debug for Bar"
+
+pub use rustdoc_trait_object_impl::Bar;
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:issue-33113.rs
+// build-aux-docs
+// ignore-cross-compile
+
+extern crate bar;
+
+// @has issue_33113/trait.Bar.html
+// @has - '//code' "for &'a char"
+// @has - '//code' "for Foo"
+pub use bar::Bar;
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(staged_api)]
+#![doc(issue_tracker_base_url = "http://issue_url/")]
+
+#![unstable(feature="test", issue = "32374")]
+
+// @has issue_32374/index.html '//*[@class="docblock short"]' \
+// '[Deprecated] [Unstable]'
+
+// @has issue_32374/struct.T.html '//*[@class="stab deprecated"]' \
+// 'Deprecated since 1.0.0: text'
+// @has - '<code>test</code>'
+// @has - '<a href="http://issue_url/32374">#32374</a>'
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+#[unstable(feature = "test", issue = "32374")]
+pub struct T;