From 24472943ce34e6ed0ac072191f8747de5acb000e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 25 Sep 2018 10:48:07 -0700 Subject: [PATCH 1/6] Add 1.29.1 release nodes Forward-port of #54397, should have included it earlier! --- RELEASES.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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) ========================== From e6ea19d7bd17cf7252d6af90781665d5e87ea156 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 25 Sep 2018 12:27:09 -0600 Subject: [PATCH 2/6] Include path in stamp hash for debuginfo tests The debuginfo tests are exposed to the environment in a couple of ways: the path to the gdb executable matters, as does the Python path used when loading lldb. This patch incorporates these paths into the hash that is written to the stamp file, so that changing the path will cause the tests to be re-run. --- src/tools/compiletest/src/runtest.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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()) } From c0ac5bac997274d9dc6801a6e061d84797f39b46 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Tue, 25 Sep 2018 16:37:31 -0400 Subject: [PATCH 3/6] ignore {std,fast,vector,this}call on non-x86 windows MSVC ignores these keywords for C/C++ and uses the standard system calling convention. Rust should do so as well. Fixes #54569. --- src/librustc_target/spec/mod.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) 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 } } From 2b3e16bfaabd07d87523a90e820fd2fa50377fbc Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 26 Sep 2018 03:07:59 +0300 Subject: [PATCH 4/6] Accept trailing comma in `cfg_attr` --- src/libsyntax/config.rs | 1 + src/test/ui/cfg-attr-trailing-comma.rs | 13 +++++++++++++ src/test/ui/cfg-attr-trailing-comma.stderr | 14 ++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 src/test/ui/cfg-attr-trailing-comma.rs create mode 100644 src/test/ui/cfg-attr-trailing-comma.stderr diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 5d978b6b9e662..ea0d1efe7e27a 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 + From c8c33953ad0c169d30e75cd39275c5403341d9f1 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Wed, 26 Sep 2018 17:32:23 +0200 Subject: [PATCH 5/6] A few cleanups and minor improvements to typeck --- src/librustc_typeck/astconv.rs | 74 +++--- src/librustc_typeck/check_unused.rs | 2 +- src/librustc_typeck/coherence/builtin.rs | 74 +++--- .../coherence/inherent_impls.rs | 3 +- src/librustc_typeck/coherence/mod.rs | 4 +- src/librustc_typeck/coherence/orphan.rs | 231 +++++++++--------- src/librustc_typeck/coherence/unsafety.rs | 90 ++++--- src/librustc_typeck/collect.rs | 96 ++++---- .../constrained_type_params.rs | 9 +- src/librustc_typeck/impl_wf_check.rs | 19 +- src/librustc_typeck/lib.rs | 98 ++++---- src/librustc_typeck/outlives/mod.rs | 2 - src/librustc_typeck/outlives/test.rs | 4 +- src/librustc_typeck/outlives/utils.rs | 12 +- src/librustc_typeck/variance/mod.rs | 2 +- 15 files changed, 339 insertions(+), 381 deletions(-) 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 efc35fad820c8..cf54c7f869388 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -54,33 +54,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"); } } } @@ -91,8 +87,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; }; @@ -118,11 +113,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() } @@ -172,12 +167,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(|| { @@ -209,9 +201,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) @@ -234,7 +226,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. From bb0abe98a7ecc92b90b1065e2544c7b25d080edc Mon Sep 17 00:00:00 2001 From: Alexander Ronald Altman Date: Wed, 26 Sep 2018 16:03:05 -0500 Subject: [PATCH 6/6] Remove useless lifetimes from `Pin` `impl`s. --- src/libcore/pin.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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

{}