diff --git a/RELEASES.md b/RELEASES.md index 819c9184364fd..08470e731d8e7 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,16 @@ +Version 1.29.1 (2018-09-25) +=========================== + +Security Notes +-------------- + +- The standard library's `str::repeat` function contained an out of bounds write + caused by an integer overflow. This has been fixed by deterministically + panicking when an overflow happens. + + Thank you to Scott McMurray for responsibily disclosing this vulnerability to + us. + Version 1.29.0 (2018-09-13) ========================== diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index d09a545aecfaf..0224560af4c76 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -293,21 +293,21 @@ where } #[unstable(feature = "pin", issue = "49150")] -impl<'a, P: fmt::Debug> fmt::Debug for Pin

{ +impl fmt::Debug for Pin

{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.pointer, f) } } #[unstable(feature = "pin", issue = "49150")] -impl<'a, P: fmt::Display> fmt::Display for Pin

{ +impl fmt::Display for Pin

{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.pointer, f) } } #[unstable(feature = "pin", issue = "49150")] -impl<'a, P: fmt::Pointer> fmt::Pointer for Pin

{ +impl fmt::Pointer for Pin

{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Pointer::fmt(&self.pointer, f) } @@ -319,10 +319,10 @@ impl<'a, P: fmt::Pointer> fmt::Pointer for Pin

{ // for other reasons, though, so we just need to take care not to allow such // impls to land in std. #[unstable(feature = "pin", issue = "49150")] -impl<'a, P, U> CoerceUnsized> for Pin

+impl CoerceUnsized> for Pin

where P: CoerceUnsized, {} #[unstable(feature = "pin", issue = "49150")] -impl<'a, P> Unpin for Pin

{} +impl

Unpin for Pin

{} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 3c68b5a7ab116..3f1e8ee55286b 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -761,7 +761,7 @@ impl Default for TargetOptions { } impl Target { - /// Given a function ABI, turn "System" into the correct ABI for this target. + /// Given a function ABI, turn it into the correct ABI for this target. pub fn adjust_abi(&self, abi: Abi) -> Abi { match abi { Abi::System => { @@ -771,6 +771,16 @@ impl Target { Abi::C } }, + // These ABI kinds are ignored on non-x86 Windows targets. + // See https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions + // and the individual pages for __stdcall et al. + Abi::Stdcall | Abi::Fastcall | Abi::Vectorcall | Abi::Thiscall => { + if self.options.is_like_windows && self.arch != "x86" { + Abi::C + } else { + abi + } + }, abi => abi } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 72502cda6e02d..95a4cb82cf3ec 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -147,7 +147,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { bound_region: ty::BrNamed(id, name) })) - // (*) -- not late-bound, won't change + // (*) -- not late-bound, won't change } None => { @@ -167,8 +167,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { }; debug!("ast_region_to_region(lifetime={:?}) yields {:?}", - lifetime, - r); + lifetime, + r); r } @@ -218,7 +218,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { span, E0632, "cannot provide explicit type parameters when `impl Trait` is \ - used in argument position." + used in argument position." }; err.emit(); @@ -538,7 +538,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { // region with the current anon region binding (in other words, // whatever & would get replaced with). debug!("create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \ - generic_args={:?})", + generic_args={:?})", def_id, self_ty, generic_args); let tcx = self.tcx(); @@ -609,7 +609,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { if default_needs_object_self(param) { struct_span_err!(tcx.sess, span, E0393, "the type parameter `{}` must be explicitly \ - specified", + specified", param.name) .span_label(span, format!("missing reference to `{}`", param.name)) @@ -623,7 +623,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { self.normalize_ty( span, tcx.at(span).type_of(param.def_id) - .subst_spanned(tcx, substs.unwrap(), Some(span)) + .subst_spanned(tcx, substs.unwrap(), Some(span)) ).into() } } else if infer_types { @@ -850,7 +850,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { binding.span, E0582, "binding for associated type `{}` references lifetime `{}`, \ - which does not appear in the trait input types", + which does not appear in the trait input types", binding.item_name, br_name) .emit(); } @@ -890,7 +890,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { ref_id, binding.span, &format!("associated type binding `{}` specified more than once", - binding.item_name) + binding.item_name) ); err.span_label(binding.span, "used more than once"); err.span_label(*prev_span, format!("first use of `{}`", binding.item_name)); @@ -993,7 +993,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { if !object_safety_violations.is_empty() { tcx.report_object_safety_error( span, principal.def_id(), object_safety_violations) - .emit(); + .emit(); return tcx.types.err; } @@ -1013,13 +1013,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { for item_def_id in associated_types { let assoc_item = tcx.associated_item(item_def_id); let trait_def_id = assoc_item.container.id(); - struct_span_err!(tcx.sess, span, E0191, - "the value of the associated type `{}` (from the trait `{}`) must be specified", - assoc_item.ident, - tcx.item_path_str(trait_def_id)) - .span_label(span, format!( - "missing associated type `{}` value", assoc_item.ident)) - .emit(); + struct_span_err!(tcx.sess, span, E0191, "the value of the associated type `{}` \ + (from the trait `{}`) must be specified", + assoc_item.ident, + tcx.item_path_str(trait_def_id)) + .span_label(span, format!("missing associated type `{}` value", + assoc_item.ident)) + .emit(); } // Dedup auto traits so that `dyn Trait + Send + Send` is the same as `dyn Trait + Send`. @@ -1031,12 +1031,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { iter::once(ty::ExistentialPredicate::Trait(*existential_principal.skip_binder())) .chain(auto_traits.into_iter().map(ty::ExistentialPredicate::AutoTrait)) .chain(existential_projections - .map(|x| ty::ExistentialPredicate::Projection(*x.skip_binder()))) + .map(|x| ty::ExistentialPredicate::Projection(*x.skip_binder()))) .collect::>(); v.sort_by(|a, b| a.stable_cmp(tcx, b)); let existential_predicates = ty::Binder::bind(tcx.mk_existential_predicates(v.into_iter())); - // Explicitly specified region bound. Use that. let region_bound = if !lifetime.is_elided() { self.ast_region_to_region(lifetime, None) @@ -1071,7 +1070,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type") .span_label(span, "ambiguous associated type") .note(&format!("specify the type using the syntax `<{} as {}>::{}`", - type_str, trait_str, name)) + type_str, trait_str, name)) .emit(); } @@ -1093,8 +1092,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { // Check that there is exactly one way to find an associated type with the // correct name. - let suitable_bounds = - traits::transitive_bounds(tcx, &bounds) + let suitable_bounds = traits::transitive_bounds(tcx, &bounds) .filter(|b| self.trait_defines_associated_type_named(b.def_id(), assoc_name)); let param_node_id = tcx.hir.as_local_node_id(ty_param_def_id).unwrap(); @@ -1109,10 +1107,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { // Checks that bounds contains exactly one element and reports appropriate // errors otherwise. fn one_bound_for_assoc_type(&self, - mut bounds: I, - ty_param_name: &str, - assoc_name: ast::Ident, - span: Span) + mut bounds: I, + ty_param_name: &str, + assoc_name: ast::Ident, + span: Span) -> Result, ErrorReported> where I: Iterator> { @@ -1120,9 +1118,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { Some(bound) => bound, None => { struct_span_err!(self.tcx().sess, span, E0220, - "associated type `{}` not found for `{}`", - assoc_name, - ty_param_name) + "associated type `{}` not found for `{}`", + assoc_name, + ty_param_name) .span_label(span, format!("associated type `{}` not found", assoc_name)) .emit(); return Err(ErrorReported); @@ -1141,14 +1139,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { for bound in bounds { let bound_span = self.tcx().associated_items(bound.def_id()).find(|item| { item.kind == ty::AssociatedKind::Type && - self.tcx().hygienic_eq(assoc_name, item.ident, bound.def_id()) + self.tcx().hygienic_eq(assoc_name, item.ident, bound.def_id()) }) .and_then(|item| self.tcx().hir.span_if_local(item.def_id)); if let Some(span) = bound_span { err.span_label(span, format!("ambiguous `{}` from `{}`", - assoc_name, - bound)); + assoc_name, + bound)); } else { span_note!(&mut err, span, "associated type `{}` could derive from `{}`", @@ -1197,8 +1195,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { } }; - let candidates = - traits::supertraits(tcx, ty::Binder::bind(trait_ref)) + let candidates = traits::supertraits(tcx, ty::Binder::bind(trait_ref)) .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name)); match self.one_bound_for_assoc_type(candidates, "Self", assoc_name, span) { @@ -1229,7 +1226,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { let (assoc_ident, def_scope) = tcx.adjust_ident(assoc_name, trait_did, ref_id); let item = tcx.associated_items(trait_did).find(|i| { Namespace::from(i.kind) == Namespace::Type && - i.ident.modern() == assoc_ident + i.ident.modern() == assoc_ident }) .expect("missing associated type"); @@ -1292,8 +1289,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { if err_for_lt { continue } err_for_lt = true; (struct_span_err!(self.tcx().sess, lt.span, E0110, - "lifetime parameters are not allowed on \ - this type"), + "lifetime parameters are not allowed on this type"), lt.span, "lifetime") } @@ -1301,7 +1297,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { if err_for_ty { continue } err_for_ty = true; (struct_span_err!(self.tcx().sess, ty.span, E0109, - "type parameters are not allowed on this type"), + "type parameters are not allowed on this type"), ty.span, "type") } @@ -1589,7 +1585,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { )); // Find any late-bound regions declared in return type that do - // not appear in the arguments. These are not wellformed. + // not appear in the arguments. These are not well-formed. // // Example: // for<'a> fn() -> &'a str <-- 'a is bad diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 5967bd1ba3eea..d9dee917b01e4 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -75,7 +75,7 @@ impl<'a, 'tcx> CheckVisitor<'a, 'tcx> { let msg = if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { format!("unused import: `{}`", snippet) } else { - "unused import".to_string() + "unused import".to_owned() }; self.tcx.lint_node(lint::builtin::UNUSED_IMPORTS, id, span, &msg); } diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index db08bf8095352..c54d9e4b47578 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -55,33 +55,29 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { } fn visit_implementation_of_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: DefId) { - match tcx.type_of(impl_did).sty { - ty::Adt(..) => {} - _ => { - // Destructors only work on nominal types. - if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_did) { - match tcx.hir.find(impl_node_id) { - Some(Node::Item(item)) => { - let span = match item.node { - ItemKind::Impl(.., ref ty, _) => ty.span, - _ => item.span, - }; - struct_span_err!(tcx.sess, - span, - E0120, - "the Drop trait may only be implemented on \ - structures") - .span_label(span, "implementing Drop requires a struct") - .emit(); - } - _ => { - bug!("didn't find impl in ast map"); - } - } + if let ty::Adt(..) = tcx.type_of(impl_did).sty { + /* do nothing */ + } else { + // Destructors only work on nominal types. + if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_did) { + if let Some(Node::Item(item)) = tcx.hir.find(impl_node_id) { + let span = match item.node { + ItemKind::Impl(.., ref ty, _) => ty.span, + _ => item.span, + }; + struct_span_err!(tcx.sess, + span, + E0120, + "the Drop trait may only be implemented on \ + structures") + .span_label(span, "implementing Drop requires a struct") + .emit(); } else { - bug!("found external impl of Drop trait on \ - something other than a struct"); + bug!("didn't find impl in ast map"); } + } else { + bug!("found external impl of Drop trait on \ + something other than a struct"); } } } @@ -92,8 +88,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: let impl_node_id = if let Some(n) = tcx.hir.as_local_node_id(impl_did) { n } else { - debug!("visit_implementation_of_copy(): impl not in this \ - crate"); + debug!("visit_implementation_of_copy(): impl not in this crate"); return; }; @@ -119,11 +114,11 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: }; let mut err = struct_span_err!(tcx.sess, - span, - E0204, - "the trait `Copy` may not be implemented for this type"); + span, + E0204, + "the trait `Copy` may not be implemented for this type"); for span in fields.iter().map(|f| tcx.def_span(f.did)) { - err.span_label(span, "this field does not implement `Copy`"); + err.span_label(span, "this field does not implement `Copy`"); } err.emit() } @@ -173,12 +168,9 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did); let coerce_unsized_trait = gcx.lang_items().coerce_unsized_trait().unwrap(); - let unsize_trait = match gcx.lang_items().require(UnsizeTraitLangItem) { - Ok(id) => id, - Err(err) => { - gcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err)); - } - }; + let unsize_trait = gcx.lang_items().require(UnsizeTraitLangItem).unwrap_or_else(|err| { + gcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err)); + }); // this provider should only get invoked for local def-ids let impl_node_id = gcx.hir.as_local_node_id(impl_did).unwrap_or_else(|| { @@ -210,9 +202,9 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, mk_ptr: &dyn Fn(Ty<'gcx>) -> Ty<'gcx>| { if (mt_a.mutbl, mt_b.mutbl) == (hir::MutImmutable, hir::MutMutable) { infcx.report_mismatched_types(&cause, - mk_ptr(mt_b.ty), - target, - ty::error::TypeError::Mutability) + mk_ptr(mt_b.ty), + target, + ty::error::TypeError::Mutability) .emit(); } (mt_a.ty, mt_b.ty, unsize_trait, None) @@ -235,7 +227,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, } (&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b)) if def_a.is_struct() && - def_b.is_struct() => { + def_b.is_struct() => { if def_a != def_b { let source_path = gcx.item_path_str(def_a.did); let target_path = gcx.item_path_str(def_b.did); diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index 52e37b8d0ce11..1955a709dbfe5 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -315,8 +315,7 @@ impl<'a, 'tcx> InherentCollect<'a, 'tcx> { E0116, "cannot define inherent `impl` for a type outside of the crate \ where the type is defined") - .span_label(item.span, - "impl for type defined outside of crate.") + .span_label(item.span, "impl for type defined outside of crate.") .note("define and implement a trait or new type instead") .emit(); } diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index ecb7a8ea8b62e..616ca97a7a75d 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -36,8 +36,8 @@ fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) { if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) { debug!("(checking implementation) adding impl for trait '{:?}', item '{}'", - trait_ref, - tcx.item_path_str(impl_def_id)); + trait_ref, + tcx.item_path_str(impl_def_id)); // Skip impls where one of the self type is an error type. // This occurs with e.g. resolve failures (#30589). diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index f9b89488232d2..b155587dddc41 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -33,131 +33,126 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> { /// reports. fn visit_item(&mut self, item: &hir::Item) { let def_id = self.tcx.hir.local_def_id(item.id); - match item.node { - hir::ItemKind::Impl(.., Some(_), _, _) => { - // "Trait" impl - debug!("coherence2::orphan check: trait impl {}", - self.tcx.hir.node_to_string(item.id)); - let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap(); - let trait_def_id = trait_ref.def_id; - let cm = self.tcx.sess.source_map(); - let sp = cm.def_span(item.span); - match traits::orphan_check(self.tcx, def_id) { - Ok(()) => {} - Err(traits::OrphanCheckErr::NoLocalInputType) => { - struct_span_err!(self.tcx.sess, - sp, - E0117, - "only traits defined in the current crate can be \ - implemented for arbitrary types") - .span_label(sp, "impl doesn't use types inside crate") - .note("the impl does not reference any types defined in this crate") - .note("define and implement a trait or new type instead") - .emit(); - return; - } - Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => { - struct_span_err!(self.tcx.sess, - sp, - E0210, - "type parameter `{}` must be used as the type parameter \ - for some local type (e.g. `MyStruct<{}>`)", - param_ty, - param_ty) - .span_label(sp, - format!("type parameter `{}` must be used as the type \ - parameter for some local type", param_ty)) - .note("only traits defined in the current crate can be implemented \ - for a type parameter") - .emit(); - return; - } + // "Trait" impl + if let hir::ItemKind::Impl(.., Some(_), _, _) = item.node { + debug!("coherence2::orphan check: trait impl {}", + self.tcx.hir.node_to_string(item.id)); + let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap(); + let trait_def_id = trait_ref.def_id; + let cm = self.tcx.sess.source_map(); + let sp = cm.def_span(item.span); + match traits::orphan_check(self.tcx, def_id) { + Ok(()) => {} + Err(traits::OrphanCheckErr::NoLocalInputType) => { + struct_span_err!(self.tcx.sess, + sp, + E0117, + "only traits defined in the current crate can be \ + implemented for arbitrary types") + .span_label(sp, "impl doesn't use types inside crate") + .note("the impl does not reference any types defined in this crate") + .note("define and implement a trait or new type instead") + .emit(); + return; + } + Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => { + struct_span_err!(self.tcx.sess, + sp, + E0210, + "type parameter `{}` must be used as the type parameter \ + for some local type (e.g. `MyStruct<{}>`)", + param_ty, + param_ty) + .span_label(sp, + format!("type parameter `{}` must be used as the type \ + parameter for some local type", param_ty)) + .note("only traits defined in the current crate can be implemented \ + for a type parameter") + .emit(); + return; } + } - // In addition to the above rules, we restrict impls of auto traits - // so that they can only be implemented on nominal types, such as structs, - // enums or foreign types. To see why this restriction exists, consider the - // following example (#22978). Imagine that crate A defines an auto trait - // `Foo` and a fn that operates on pairs of types: - // - // ``` - // // Crate A - // auto trait Foo { } - // fn two_foos(..) { - // one_foo::<(A,B)>(..) - // } - // fn one_foo(..) { .. } - // ``` - // - // This type-checks fine; in particular the fn - // `two_foos` is able to conclude that `(A,B):Foo` - // because `A:Foo` and `B:Foo`. - // - // Now imagine that crate B comes along and does the following: - // - // ``` - // struct A { } - // struct B { } - // impl Foo for A { } - // impl Foo for B { } - // impl !Send for (A, B) { } - // ``` - // - // This final impl is legal according to the orpan - // rules, but it invalidates the reasoning from - // `two_foos` above. - debug!("trait_ref={:?} trait_def_id={:?} trait_is_auto={}", - trait_ref, - trait_def_id, - self.tcx.trait_is_auto(trait_def_id)); - if self.tcx.trait_is_auto(trait_def_id) && - !trait_def_id.is_local() { - let self_ty = trait_ref.self_ty(); - let opt_self_def_id = match self_ty.sty { - ty::Adt(self_def, _) => Some(self_def.did), - ty::Foreign(did) => Some(did), - _ => None, - }; + // In addition to the above rules, we restrict impls of auto traits + // so that they can only be implemented on nominal types, such as structs, + // enums or foreign types. To see why this restriction exists, consider the + // following example (#22978). Imagine that crate A defines an auto trait + // `Foo` and a fn that operates on pairs of types: + // + // ``` + // // Crate A + // auto trait Foo { } + // fn two_foos(..) { + // one_foo::<(A,B)>(..) + // } + // fn one_foo(..) { .. } + // ``` + // + // This type-checks fine; in particular the fn + // `two_foos` is able to conclude that `(A,B):Foo` + // because `A:Foo` and `B:Foo`. + // + // Now imagine that crate B comes along and does the following: + // + // ``` + // struct A { } + // struct B { } + // impl Foo for A { } + // impl Foo for B { } + // impl !Send for (A, B) { } + // ``` + // + // This final impl is legal according to the orpan + // rules, but it invalidates the reasoning from + // `two_foos` above. + debug!("trait_ref={:?} trait_def_id={:?} trait_is_auto={}", + trait_ref, + trait_def_id, + self.tcx.trait_is_auto(trait_def_id)); + if self.tcx.trait_is_auto(trait_def_id) && + !trait_def_id.is_local() { + let self_ty = trait_ref.self_ty(); + let opt_self_def_id = match self_ty.sty { + ty::Adt(self_def, _) => Some(self_def.did), + ty::Foreign(did) => Some(did), + _ => None, + }; - let msg = match opt_self_def_id { - // We only want to permit nominal types, but not *all* nominal types. - // They must be local to the current crate, so that people - // can't do `unsafe impl Send for Rc` or - // `impl !Send for Box`. - Some(self_def_id) => { - if self_def_id.is_local() { - None - } else { - Some(( - format!("cross-crate traits with a default impl, like `{}`, \ - can only be implemented for a struct/enum type \ - defined in the current crate", - self.tcx.item_path_str(trait_def_id)), - "can't implement cross-crate trait for type in another crate" - )) - } - } - _ => { - Some((format!("cross-crate traits with a default impl, like `{}`, can \ - only be implemented for a struct/enum type, not `{}`", - self.tcx.item_path_str(trait_def_id), - self_ty), - "can't implement cross-crate trait with a default impl for \ - non-struct/enum type")) + let msg = match opt_self_def_id { + // We only want to permit nominal types, but not *all* nominal types. + // They must be local to the current crate, so that people + // can't do `unsafe impl Send for Rc` or + // `impl !Send for Box`. + Some(self_def_id) => { + if self_def_id.is_local() { + None + } else { + Some(( + format!("cross-crate traits with a default impl, like `{}`, \ + can only be implemented for a struct/enum type \ + defined in the current crate", + self.tcx.item_path_str(trait_def_id)), + "can't implement cross-crate trait for type in another crate" + )) } - }; - - if let Some((msg, label)) = msg { - struct_span_err!(self.tcx.sess, sp, E0321, "{}", msg) - .span_label(sp, label) - .emit(); - return; } + _ => { + Some((format!("cross-crate traits with a default impl, like `{}`, can \ + only be implemented for a struct/enum type, not `{}`", + self.tcx.item_path_str(trait_def_id), + self_ty), + "can't implement cross-crate trait with a default impl for \ + non-struct/enum type")) + } + }; + + if let Some((msg, label)) = msg { + struct_span_err!(self.tcx.sess, sp, E0321, "{}", msg) + .span_label(sp, label) + .emit(); + return; } } - _ => { - // Not an impl - } } } diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs index 9e19854a571fc..bdbf93ddec286 100644 --- a/src/librustc_typeck/coherence/unsafety.rs +++ b/src/librustc_typeck/coherence/unsafety.rs @@ -29,52 +29,49 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> { item: &'v hir::Item, impl_generics: Option<&hir::Generics>, unsafety: hir::Unsafety, - polarity: hir::ImplPolarity) { - match self.tcx.impl_trait_ref(self.tcx.hir.local_def_id(item.id)) { - None => {} - - Some(trait_ref) => { - let trait_def = self.tcx.trait_def(trait_ref.def_id); - let unsafe_attr = impl_generics.and_then(|generics| { - generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle") - }); - match (trait_def.unsafety, unsafe_attr, unsafety, polarity) { - (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => { - span_err!(self.tcx.sess, - item.span, - E0199, - "implementing the trait `{}` is not unsafe", - trait_ref); - } + polarity: hir::ImplPolarity) + { + if let Some(trait_ref) = self.tcx.impl_trait_ref(self.tcx.hir.local_def_id(item.id)) { + let trait_def = self.tcx.trait_def(trait_ref.def_id); + let unsafe_attr = impl_generics.and_then(|generics| { + generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle") + }); + match (trait_def.unsafety, unsafe_attr, unsafety, polarity) { + (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => { + span_err!(self.tcx.sess, + item.span, + E0199, + "implementing the trait `{}` is not unsafe", + trait_ref); + } - (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => { - span_err!(self.tcx.sess, - item.span, - E0200, - "the trait `{}` requires an `unsafe impl` declaration", - trait_ref); - } + (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => { + span_err!(self.tcx.sess, + item.span, + E0200, + "the trait `{}` requires an `unsafe impl` declaration", + trait_ref); + } - (Unsafety::Normal, Some(attr_name), Unsafety::Normal, - hir::ImplPolarity::Positive) => - { - span_err!(self.tcx.sess, - item.span, - E0569, - "requires an `unsafe impl` declaration due to `#[{}]` attribute", - attr_name); - } + (Unsafety::Normal, Some(attr_name), Unsafety::Normal, + hir::ImplPolarity::Positive) => + { + span_err!(self.tcx.sess, + item.span, + E0569, + "requires an `unsafe impl` declaration due to `#[{}]` attribute", + attr_name); + } - (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => { - // Reported in AST validation - self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl"); - } - (_, _, Unsafety::Normal, hir::ImplPolarity::Negative) | - (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) | - (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive) | - (Unsafety::Normal, None, Unsafety::Normal, _) => { - // OK - } + (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => { + // Reported in AST validation + self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl"); + } + (_, _, Unsafety::Normal, hir::ImplPolarity::Negative) | + (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) | + (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive) | + (Unsafety::Normal, None, Unsafety::Normal, _) => { + // OK } } } @@ -83,11 +80,8 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> { impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for UnsafetyChecker<'cx, 'tcx> { fn visit_item(&mut self, item: &'v hir::Item) { - match item.node { - hir::ItemKind::Impl(unsafety, polarity, _, ref generics, ..) => { - self.check_unsafety_coherence(item, Some(generics), unsafety, polarity); - } - _ => {} + if let hir::ItemKind::Impl(unsafety, polarity, _, ref generics, ..) = item.node { + self.check_unsafety_coherence(item, Some(generics), unsafety, polarity); } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index bb5753f432a02..d3134b63bb661 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -56,14 +56,16 @@ use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc::hir::GenericParamKind; use rustc::hir::{self, CodegenFnAttrFlags, CodegenFnAttrs, Unsafety}; +use std::iter; + /////////////////////////////////////////////////////////////////////////// // Main entry point pub fn collect_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut visitor = CollectItemTypesVisitor { tcx: tcx }; tcx.hir - .krate() - .visit_all_item_likes(&mut visitor.as_deep_visitor()); + .krate() + .visit_all_item_likes(&mut visitor.as_deep_visitor()); } pub fn provide(providers: &mut Providers) { @@ -195,7 +197,8 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { E0121, "the type placeholder `_` is not allowed within types on item signatures" ).span_label(span, "not allowed in type signatures") - .emit(); + .emit(); + self.tcx().types.err } @@ -574,8 +577,8 @@ fn convert_variant<'a, 'tcx>( "field `{}` is already declared", f.ident ).span_label(f.span, "field already declared") - .span_label(prev_span, format!("`{}` first declared here", f.ident)) - .emit(); + .span_label(prev_span, format!("`{}` first declared here", f.ident)) + .emit(); } else { seen_fields.insert(f.ident.modern(), f.span); } @@ -819,14 +822,11 @@ fn has_late_bound_regions<'a, 'tcx>( has_late_bound_regions: None, }; for param in &generics.params { - match param.kind { - GenericParamKind::Lifetime { .. } => { - let hir_id = tcx.hir.node_to_hir_id(param.id); - if tcx.is_late_bound(hir_id) { - return Some(param.span); - } + if let GenericParamKind::Lifetime { .. } = param.kind { + let hir_id = tcx.hir.node_to_hir_id(param.id); + if tcx.is_late_bound(hir_id) { + return Some(param.span); } - _ => {} } } visitor.visit_fn_decl(decl); @@ -1309,6 +1309,7 @@ fn find_existential_constraints<'a, 'tcx>( def_id: DefId, found: Option<(Span, ty::Ty<'tcx>)>, } + impl<'a, 'tcx> ConstraintLocator<'a, 'tcx> { fn check(&mut self, def_id: DefId) { trace!("checking {:?}", def_id); @@ -1342,6 +1343,7 @@ fn find_existential_constraints<'a, 'tcx>( } } } + impl<'a, 'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> { intravisit::NestedVisitorMap::All(&self.tcx.hir) @@ -1368,6 +1370,7 @@ fn find_existential_constraints<'a, 'tcx>( intravisit::walk_trait_item(self, it); } } + let mut locator = ConstraintLocator { def_id, tcx, @@ -1375,7 +1378,9 @@ fn find_existential_constraints<'a, 'tcx>( }; let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); let parent = tcx.hir.get_parent(node_id); + trace!("parent_id: {:?}", parent); + if parent == ast::CRATE_NODE_ID { intravisit::walk_crate(&mut locator, tcx.hir.krate()); } else { @@ -1390,6 +1395,7 @@ fn find_existential_constraints<'a, 'tcx>( ), } } + match locator.found { Some((_, ty)) => ty, None => { @@ -1780,17 +1786,14 @@ fn explicit_predicates_of<'a, 'tcx>( // Collect the predicates that were written inline by the user on each // type parameter (e.g., ``). for param in &ast_generics.params { - match param.kind { - GenericParamKind::Type { .. } => { - let name = param.name.ident().as_interned_str(); - let param_ty = ty::ParamTy::new(index, name).to_ty(tcx); - index += 1; - - let sized = SizedByDefault::Yes; - let bounds = compute_bounds(&icx, param_ty, ¶m.bounds, sized, param.span); - predicates.extend(bounds.predicates(tcx, param_ty)); - } - _ => {} + if let GenericParamKind::Type { .. } = param.kind { + let name = param.name.ident().as_interned_str(); + let param_ty = ty::ParamTy::new(index, name).to_ty(tcx); + index += 1; + + let sized = SizedByDefault::Yes; + let bounds = compute_bounds(&icx, param_ty, ¶m.bounds, sized, param.span); + predicates.extend(bounds.predicates(tcx, param_ty)); } } @@ -1828,8 +1831,9 @@ fn explicit_predicates_of<'a, 'tcx>( &mut projections, ); - predicates.push(trait_ref.to_predicate()); - predicates.extend(projections.iter().map(|p| p.to_predicate())); + predicates.extend( + iter::once(trait_ref.to_predicate()).chain( + projections.iter().map(|p| p.to_predicate()))); } &hir::GenericBound::Outlives(ref lifetime) => { @@ -1843,7 +1847,8 @@ fn explicit_predicates_of<'a, 'tcx>( &hir::WherePredicate::RegionPredicate(ref region_pred) => { let r1 = AstConv::ast_region_to_region(&icx, ®ion_pred.lifetime, None); - for bound in ®ion_pred.bounds { + + predicates.extend(region_pred.bounds.iter().map(|bound| { let r2 = match bound { hir::GenericBound::Outlives(lt) => { AstConv::ast_region_to_region(&icx, lt, None) @@ -1851,8 +1856,9 @@ fn explicit_predicates_of<'a, 'tcx>( _ => bug!(), }; let pred = ty::Binder::bind(ty::OutlivesPredicate(r1, r2)); - predicates.push(ty::Predicate::RegionOutlives(pred)) - } + + ty::Predicate::RegionOutlives(pred) + })) } &hir::WherePredicate::EqPredicate(..) => { @@ -1867,9 +1873,7 @@ fn explicit_predicates_of<'a, 'tcx>( let trait_item = tcx.hir.trait_item(trait_item_ref.id); let bounds = match trait_item.node { hir::TraitItemKind::Type(ref bounds, _) => bounds, - _ => { - return vec![].into_iter(); - } + _ => return vec![].into_iter() }; let assoc_ty = @@ -1930,6 +1934,7 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>( ) -> Bounds<'tcx> { let mut region_bounds = vec![]; let mut trait_bounds = vec![]; + for ast_bound in ast_bounds { match *ast_bound { hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => trait_bounds.push(b), @@ -2020,13 +2025,13 @@ fn compute_sig_of_foreign_fn_decl<'a, 'tcx>( let check = |ast_ty: &hir::Ty, ty: Ty| { if ty.is_simd() { tcx.sess - .struct_span_err( - ast_ty.span, - &format!( - "use of SIMD type `{}` in FFI is highly experimental and \ - may result in invalid code", - tcx.hir.node_to_pretty_string(ast_ty.id) - ), + .struct_span_err( + ast_ty.span, + &format!( + "use of SIMD type `{}` in FFI is highly experimental and \ + may result in invalid code", + tcx.hir.node_to_pretty_string(ast_ty.id) + ), ) .help("add #![feature(simd_ffi)] to the crate attributes to enable") .emit(); @@ -2089,7 +2094,7 @@ fn from_target_feature( }; // We allow comma separation to enable multiple features - for feature in value.as_str().split(',') { + target_features.extend(value.as_str().split(',').filter_map(|feature| { // Only allow whitelisted features per platform let feature_gate = match whitelist.get(feature) { Some(g) => g, @@ -2108,7 +2113,7 @@ fn from_target_feature( } } err.emit(); - continue; + return None; } }; @@ -2135,10 +2140,11 @@ fn from_target_feature( feature_gate::GateIssue::Language, &format!("the target feature `{}` is currently unstable", feature), ); - continue; + return None; } - target_features.push(Symbol::intern(feature)); - } + + Some(Symbol::intern(feature)) + })); } } @@ -2171,7 +2177,7 @@ fn linkage_by_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, name: & tcx.sess.span_fatal(span, "invalid linkage specified") } else { tcx.sess - .fatal(&format!("invalid linkage specified: {}", name)) + .fatal(&format!("invalid linkage specified: {}", name)) } } } @@ -2269,7 +2275,7 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen E0558, "`export_name` attribute has invalid format" ).span_label(attr.span, "did you mean #[export_name=\"*\"]?") - .emit(); + .emit(); } } else if attr.check_name("target_feature") { if tcx.fn_sig(id).unsafety() == Unsafety::Normal { diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs index 1b481fc5a7d31..2fe9088b901c1 100644 --- a/src/librustc_typeck/constrained_type_params.rs +++ b/src/librustc_typeck/constrained_type_params.rs @@ -76,11 +76,8 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector { } fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { - match *r { - ty::ReEarlyBound(data) => { - self.parameters.push(Parameter::from(data)); - } - _ => {} + if let ty::ReEarlyBound(data) = *r { + self.parameters.push(Parameter::from(data)); } false } @@ -203,6 +200,6 @@ pub fn setup_constraining_predicates<'tcx>(tcx: TyCtxt, } debug!("setup_constraining_predicates: predicates={:?} \ i={} impl_trait_ref={:?} input_parameters={:?}", - predicates, i, impl_trait_ref, input_parameters); + predicates, i, impl_trait_ref, input_parameters); } } diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 11260b8f11e12..f2b1ad58677fc 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -71,15 +71,12 @@ struct ImplWfCheck<'a, 'tcx: 'a> { impl<'a, 'tcx> ItemLikeVisitor<'tcx> for ImplWfCheck<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { - match item.node { - hir::ItemKind::Impl(.., ref impl_item_refs) => { - let impl_def_id = self.tcx.hir.local_def_id(item.id); - enforce_impl_params_are_constrained(self.tcx, - impl_def_id, - impl_item_refs); - enforce_impl_items_are_distinct(self.tcx, impl_item_refs); - } - _ => { } + if let hir::ItemKind::Impl(.., ref impl_item_refs) = item.node { + let impl_def_id = self.tcx.hir.local_def_id(item.id); + enforce_impl_params_are_constrained(self.tcx, + impl_def_id, + impl_item_refs); + enforce_impl_items_are_distinct(self.tcx, impl_item_refs); } } @@ -182,7 +179,7 @@ fn enforce_impl_items_are_distinct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let impl_item = tcx.hir.impl_item(impl_item_ref.id); let seen_items = match impl_item.node { hir::ImplItemKind::Type(_) => &mut seen_type_items, - _ => &mut seen_value_items, + _ => &mut seen_value_items, }; match seen_items.entry(impl_item.ident.modern()) { Occupied(entry) => { @@ -191,7 +188,7 @@ fn enforce_impl_items_are_distinct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item.ident); err.span_label(*entry.get(), format!("previous definition of `{}` here", - impl_item.ident)); + impl_item.ident)); err.span_label(impl_item.span, "duplicate definition"); err.emit(); } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index c9aa0339dd469..3ca93f2dbe185 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -146,7 +146,7 @@ fn require_c_abi_if_variadic(tcx: TyCtxt, span: Span) { if decl.variadic && !(abi == Abi::C || abi == Abi::Cdecl) { let mut err = struct_span_err!(tcx.sess, span, E0045, - "variadic function must have C or cdecl calling convention"); + "variadic function must have C or cdecl calling convention"); err.span_label(span, "variadics require C or cdecl calling convention").emit(); } } @@ -186,35 +186,29 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let main_t = tcx.type_of(main_def_id); match main_t.sty { ty::FnDef(..) => { - match tcx.hir.find(main_id) { - Some(Node::Item(it)) => { - match it.node { - hir::ItemKind::Fn(.., ref generics, _) => { - let mut error = false; - if !generics.params.is_empty() { - let msg = "`main` function is not allowed to have generic \ - parameters".to_string(); - let label = "`main` cannot have generic parameters".to_string(); - struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg) - .span_label(generics.span, label) - .emit(); - error = true; - } - if let Some(sp) = generics.where_clause.span() { - struct_span_err!(tcx.sess, sp, E0646, - "`main` function is not allowed to have a `where` clause") - .span_label(sp, "`main` cannot have a `where` clause") - .emit(); - error = true; - } - if error { - return; - } - } - _ => () + if let Some(Node::Item(it)) = tcx.hir.find(main_id) { + if let hir::ItemKind::Fn(.., ref generics, _) = it.node { + let mut error = false; + if !generics.params.is_empty() { + let msg = "`main` function is not allowed to have generic \ + parameters".to_owned(); + let label = "`main` cannot have generic parameters".to_string(); + struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg) + .span_label(generics.span, label) + .emit(); + error = true; + } + if let Some(sp) = generics.where_clause.span() { + struct_span_err!(tcx.sess, sp, E0646, + "`main` function is not allowed to have a `where` clause") + .span_label(sp, "`main` cannot have a `where` clause") + .emit(); + error = true; + } + if error { + return; } } - _ => () } let actual = tcx.fn_sig(main_def_id); @@ -258,34 +252,28 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let start_t = tcx.type_of(start_def_id); match start_t.sty { ty::FnDef(..) => { - match tcx.hir.find(start_id) { - Some(Node::Item(it)) => { - match it.node { - hir::ItemKind::Fn(.., ref generics, _) => { - let mut error = false; - if !generics.params.is_empty() { - struct_span_err!(tcx.sess, generics.span, E0132, - "start function is not allowed to have type parameters") - .span_label(generics.span, - "start function cannot have type parameters") - .emit(); - error = true; - } - if let Some(sp) = generics.where_clause.span() { - struct_span_err!(tcx.sess, sp, E0647, - "start function is not allowed to have a `where` clause") - .span_label(sp, "start function cannot have a `where` clause") - .emit(); - error = true; - } - if error { - return; - } - } - _ => () + if let Some(Node::Item(it)) = tcx.hir.find(start_id) { + if let hir::ItemKind::Fn(.., ref generics, _) = it.node { + let mut error = false; + if !generics.params.is_empty() { + struct_span_err!(tcx.sess, generics.span, E0132, + "start function is not allowed to have type parameters") + .span_label(generics.span, + "start function cannot have type parameters") + .emit(); + error = true; + } + if let Some(sp) = generics.where_clause.span() { + struct_span_err!(tcx.sess, sp, E0647, + "start function is not allowed to have a `where` clause") + .span_label(sp, "start function cannot have a `where` clause") + .emit(); + error = true; + } + if error { + return; } } - _ => () } let se_ty = tcx.mk_fn_ptr(ty::Binder::bind( @@ -388,6 +376,7 @@ pub fn hir_ty_to_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_ty: &hir::Ty) -> let env_node_id = tcx.hir.get_parent(hir_ty.id); let env_def_id = tcx.hir.local_def_id(env_node_id); let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id); + astconv::AstConv::ast_ty_to_ty(&item_cx, hir_ty) } @@ -403,6 +392,7 @@ pub fn hir_trait_to_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_trait: let principal = astconv::AstConv::instantiate_poly_trait_ref_inner( &item_cx, hir_trait, tcx.types.err, &mut projections, true ); + (principal, projections) } diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs index 63a424936eb4c..cca77b20d9b30 100644 --- a/src/librustc_typeck/outlives/mod.rs +++ b/src/librustc_typeck/outlives/mod.rs @@ -55,9 +55,7 @@ fn inferred_outlives_of<'a, 'tcx>( .iter() .map(|out_pred| match out_pred { ty::Predicate::RegionOutlives(p) => p.to_string(), - ty::Predicate::TypeOutlives(p) => p.to_string(), - err => bug!("unexpected predicate {:?}", err), }).collect(); pred.sort(); diff --git a/src/librustc_typeck/outlives/test.rs b/src/librustc_typeck/outlives/test.rs index c3c2ae667ddd9..48c495e1c9317 100644 --- a/src/librustc_typeck/outlives/test.rs +++ b/src/librustc_typeck/outlives/test.rs @@ -14,8 +14,8 @@ use rustc::ty::TyCtxt; pub fn test_inferred_outlives<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.hir - .krate() - .visit_all_item_likes(&mut OutlivesTest { tcx }); + .krate() + .visit_all_item_likes(&mut OutlivesTest { tcx }); } struct OutlivesTest<'a, 'tcx: 'a> { diff --git a/src/librustc_typeck/outlives/utils.rs b/src/librustc_typeck/outlives/utils.rs index 0d833c50d7e3b..6bf7a3501bed9 100644 --- a/src/librustc_typeck/outlives/utils.rs +++ b/src/librustc_typeck/outlives/utils.rs @@ -148,15 +148,9 @@ fn is_free_region<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, region: Region<'_>) -> bool // field: &'static T, // this would generate a ReStatic // } RegionKind::ReStatic => { - if tcx - .sess - .features_untracked() - .infer_static_outlives_requirements - { - true - } else { - false - } + tcx.sess + .features_untracked() + .infer_static_outlives_requirements } // Late-bound regions can appear in `fn` types: diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs index aaa0fd8e099ef..25f6b259e96bc 100644 --- a/src/librustc_typeck/variance/mod.rs +++ b/src/librustc_typeck/variance/mod.rs @@ -55,7 +55,7 @@ fn crate_variances<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) } fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) - -> Lrc> { + -> Lrc> { let id = tcx.hir.as_local_node_id(item_def_id).expect("expected local def-id"); let unsupported = || { // Variance not relevant. diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 3d9f4a92f818a..a9ce236557779 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -90,6 +90,7 @@ impl<'a> StripUnconfigured<'a> { parser.expect(&token::Comma)?; let lo = parser.span.lo(); let (path, tokens) = parser.parse_meta_item_unrestricted()?; + parser.eat(&token::Comma); // Optional trailing comma parser.expect(&token::CloseDelim(token::Paren))?; Ok((cfg, path, tokens, parser.prev_span.with_lo(lo))) }) { diff --git a/src/test/ui/cfg-attr-trailing-comma.rs b/src/test/ui/cfg-attr-trailing-comma.rs new file mode 100644 index 0000000000000..21e00544ca00b --- /dev/null +++ b/src/test/ui/cfg-attr-trailing-comma.rs @@ -0,0 +1,13 @@ +// compile-flags: --cfg TRUE + +#[cfg_attr(TRUE, inline,)] // OK +fn f() {} + +#[cfg_attr(FALSE, inline,)] // OK +fn g() {} + +#[cfg_attr(TRUE, inline,,)] //~ ERROR expected `)`, found `,` +fn h() {} + +#[cfg_attr(FALSE, inline,,)] //~ ERROR expected `)`, found `,` +fn i() {} diff --git a/src/test/ui/cfg-attr-trailing-comma.stderr b/src/test/ui/cfg-attr-trailing-comma.stderr new file mode 100644 index 0000000000000..76a470417e9ed --- /dev/null +++ b/src/test/ui/cfg-attr-trailing-comma.stderr @@ -0,0 +1,14 @@ +error: expected `)`, found `,` + --> $DIR/cfg-attr-trailing-comma.rs:9:25 + | +LL | #[cfg_attr(TRUE, inline,,)] //~ ERROR expected `)`, found `,` + | ^ expected `)` + +error: expected `)`, found `,` + --> $DIR/cfg-attr-trailing-comma.rs:12:26 + | +LL | #[cfg_attr(FALSE, inline,,)] //~ ERROR expected `)`, found `,` + | ^ expected `)` + +error: aborting due to 2 previous errors + diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 401dec7b184b1..f1a275b05c91b 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -224,6 +224,19 @@ pub fn run(config: Config, testpaths: &TestPaths, revision: Option<&str>) { pub fn compute_stamp_hash(config: &Config) -> String { let mut hash = DefaultHasher::new(); config.stage_id.hash(&mut hash); + match config.mode { + DebugInfoGdb => match config.gdb { + None => env::var_os("PATH").hash(&mut hash), + Some(ref s) if s.is_empty() => env::var_os("PATH").hash(&mut hash), + Some(ref s) => s.hash(&mut hash), + }, + DebugInfoLldb => { + env::var_os("PATH").hash(&mut hash); + env::var_os("PYTHONPATH").hash(&mut hash); + }, + + _ => {}, + }; format!("{:x}", hash.finish()) }