From 98eb29cbba66561cf184f2d7f4277b38bd6b2aad Mon Sep 17 00:00:00 2001 From: Matthew McAllister Date: Sun, 24 May 2020 17:54:30 -0700 Subject: [PATCH 01/19] Fix trait alias inherent impl resolution Fixes #60021 and #72415. --- src/librustc_typeck/check/method/probe.rs | 3 ++- .../issue-60021-assoc-method-resolve.rs | 19 +++++++++++++++++++ .../issue-72415-assoc-const-resolve.rs | 14 ++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/traits/trait-alias/issue-60021-assoc-method-resolve.rs create mode 100644 src/test/ui/traits/trait-alias/issue-72415-assoc-const-resolve.rs diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index e21db9035e25d..33290b5ca82ba 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -795,6 +795,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) { // FIXME: do we want to commit to this behavior for param bounds? + debug!("assemble_inherent_candidates_from_param(param_ty={:?})", param_ty); let bounds = self.param_env.caller_bounds.iter().filter_map(|predicate| match *predicate { ty::Predicate::Trait(ref trait_predicate, _) => { @@ -949,7 +950,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { import_ids: import_ids.clone(), kind: TraitCandidate(new_trait_ref), }, - true, + false, ); }); } else { diff --git a/src/test/ui/traits/trait-alias/issue-60021-assoc-method-resolve.rs b/src/test/ui/traits/trait-alias/issue-60021-assoc-method-resolve.rs new file mode 100644 index 0000000000000..5e27ed3c6460e --- /dev/null +++ b/src/test/ui/traits/trait-alias/issue-60021-assoc-method-resolve.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(trait_alias)] + +trait SomeTrait { + fn map(&self) {} +} + +impl SomeTrait for Option {} + +trait SomeAlias = SomeTrait; + +fn main() { + let x = Some(123); + // This should resolve to the trait impl for Option + Option::map(x, |z| z); + // This should resolve to the trait impl for SomeTrait + SomeTrait::map(&x); +} diff --git a/src/test/ui/traits/trait-alias/issue-72415-assoc-const-resolve.rs b/src/test/ui/traits/trait-alias/issue-72415-assoc-const-resolve.rs new file mode 100644 index 0000000000000..e49125d10249d --- /dev/null +++ b/src/test/ui/traits/trait-alias/issue-72415-assoc-const-resolve.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(trait_alias)] + +trait Bounded { const MAX: Self; } + +impl Bounded for u32 { + // This should correctly resolve to the associated const in the inherent impl of u32. + const MAX: Self = u32::MAX; +} + +trait Num = Bounded + Copy; + +fn main() {} From 738f8487fd78a7d860be4e65eee85c9a0e957c13 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Mon, 25 May 2020 15:33:34 -0400 Subject: [PATCH 02/19] stabilize vec_drain_as_slice --- src/liballoc/vec.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index d26cd77aae4b7..9a32b80a81efc 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2747,19 +2747,25 @@ impl<'a, T> Drain<'a, T> { /// # Examples /// /// ``` - /// # #![feature(vec_drain_as_slice)] /// let mut vec = vec!['a', 'b', 'c']; /// let mut drain = vec.drain(..); /// assert_eq!(drain.as_slice(), &['a', 'b', 'c']); /// let _ = drain.next().unwrap(); /// assert_eq!(drain.as_slice(), &['b', 'c']); /// ``` - #[unstable(feature = "vec_drain_as_slice", reason = "recently added", issue = "58957")] + #[stable(feature = "vec_drain_as_slice", since = "1.46.0")] pub fn as_slice(&self) -> &[T] { self.iter.as_slice() } } +#[stable(feature = "vec_drain_as_slice", since = "1.46.0")] +impl<'a, T> AsRef<[T]> for Drain<'a, T> { + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + #[stable(feature = "drain", since = "1.6.0")] unsafe impl Sync for Drain<'_, T> {} #[stable(feature = "drain", since = "1.6.0")] From 754da8849c18c45ff2fd2e77213f8371de488f80 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 11 Jun 2020 13:42:22 -0400 Subject: [PATCH 03/19] Make `fn_arg_names` return `Ident` instead of symbol Also, implement this query for the local crate, not just foreign crates. --- src/librustc_metadata/rmeta/decoder.rs | 4 ++-- src/librustc_metadata/rmeta/encoder.rs | 16 +++++----------- src/librustc_metadata/rmeta/mod.rs | 4 ++-- src/librustc_middle/hir/map/mod.rs | 9 ++++++++- src/librustc_middle/hir/mod.rs | 20 ++++++++++++++++---- src/librustc_middle/query/mod.rs | 2 +- 6 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index f5a9dceb78295..b2afdd0b4e13f 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -1317,13 +1317,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } - fn get_fn_param_names(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [Symbol] { + fn get_fn_param_names(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [Ident] { let param_names = match self.kind(id) { EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).param_names, EntryKind::AssocFn(data) => data.decode(self).fn_data.param_names, _ => Lazy::empty(), }; - tcx.arena.alloc_from_iter(param_names.decode(self)) + tcx.arena.alloc_from_iter(param_names.decode((self, tcx))) } fn exported_symbols( diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 64ccd46a744f5..60a5bb4340513 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -30,7 +30,7 @@ use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt}; use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder}; use rustc_session::config::CrateType; use rustc_span::source_map::Spanned; -use rustc_span::symbol::{kw, sym, Ident, Symbol}; +use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{self, ExternalSource, FileName, SourceFile, Span}; use rustc_target::abi::VariantIdx; use std::hash::Hash; @@ -997,18 +997,12 @@ impl EncodeContext<'tcx> { } } - fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) -> Lazy<[Symbol]> { - self.tcx.dep_graph.with_ignore(|| { - let body = self.tcx.hir().body(body_id); - self.lazy(body.params.iter().map(|arg| match arg.pat.kind { - hir::PatKind::Binding(_, _, ident, _) => ident.name, - _ => kw::Invalid, - })) - }) + fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) -> Lazy<[Ident]> { + self.tcx.dep_graph.with_ignore(|| self.lazy(self.tcx.hir().body_param_names(body_id))) } - fn encode_fn_param_names(&mut self, param_names: &[Ident]) -> Lazy<[Symbol]> { - self.lazy(param_names.iter().map(|ident| ident.name)) + fn encode_fn_param_names(&mut self, param_names: &[Ident]) -> Lazy<[Ident]> { + self.lazy(param_names.iter()) } fn encode_optimized_mir(&mut self, def_id: LocalDefId) { diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index 89d525eb80b8c..1cf86c7660ee4 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -19,7 +19,7 @@ use rustc_serialize::opaque::Encoder; use rustc_session::config::SymbolManglingVersion; use rustc_session::CrateDisambiguator; use rustc_span::edition::Edition; -use rustc_span::symbol::Symbol; +use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{self, Span}; use rustc_target::spec::{PanicStrategy, TargetTriple}; @@ -327,7 +327,7 @@ struct ModData { struct FnData { asyncness: hir::IsAsync, constness: hir::Constness, - param_names: Lazy<[Symbol]>, + param_names: Lazy<[Ident]>, } #[derive(RustcEncodable, RustcDecodable)] diff --git a/src/librustc_middle/hir/map/mod.rs b/src/librustc_middle/hir/map/mod.rs index b1dafb3c88585..12c7b18d06988 100644 --- a/src/librustc_middle/hir/map/mod.rs +++ b/src/librustc_middle/hir/map/mod.rs @@ -14,7 +14,7 @@ use rustc_hir::*; use rustc_index::vec::IndexVec; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::Spanned; -use rustc_span::symbol::{kw, Symbol}; +use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::Span; use rustc_target::spec::abi::Abi; @@ -375,6 +375,13 @@ impl<'hir> Map<'hir> { }) } + pub fn body_param_names(&self, id: BodyId) -> impl Iterator + 'hir { + self.body(id).params.iter().map(|arg| match arg.pat.kind { + PatKind::Binding(_, _, ident, _) => ident, + _ => Ident::new(kw::Invalid, rustc_span::DUMMY_SP), + }) + } + /// Returns the `BodyOwnerKind` of this `LocalDefId`. /// /// Panics if `LocalDefId` does not have an associated body. diff --git a/src/librustc_middle/hir/mod.rs b/src/librustc_middle/hir/mod.rs index 1e3676496ce39..e152d11c081a1 100644 --- a/src/librustc_middle/hir/mod.rs +++ b/src/librustc_middle/hir/mod.rs @@ -12,10 +12,7 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE}; -use rustc_hir::Body; -use rustc_hir::HirId; -use rustc_hir::ItemLocalId; -use rustc_hir::Node; +use rustc_hir::*; use rustc_index::vec::IndexVec; pub struct Owner<'tcx> { @@ -79,5 +76,20 @@ pub fn provide(providers: &mut Providers<'_>) { }; providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature; providers.hir_owner_nodes = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_deref(); + providers.fn_arg_names = |tcx, id| { + let hir = tcx.hir(); + let hir_id = hir.as_local_hir_id(id.expect_local()); + if let Some(body_id) = hir.maybe_body_owned_by(hir_id) { + tcx.arena.alloc_from_iter(hir.body_param_names(body_id)) + } else if let Node::TraitItem(&TraitItem { + kind: TraitItemKind::Fn(_, TraitFn::Required(idents)), + .. + }) = hir.get(hir_id) + { + tcx.arena.alloc_slice(idents) + } else { + span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", id); + } + }; map::provide(providers); } diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs index 4d7e7882e426c..d65e01b145ac6 100644 --- a/src/librustc_middle/query/mod.rs +++ b/src/librustc_middle/query/mod.rs @@ -700,7 +700,7 @@ rustc_queries! { } Other { - query fn_arg_names(def_id: DefId) -> &'tcx [Symbol] { + query fn_arg_names(def_id: DefId) -> &'tcx [rustc_span::symbol::Ident] { desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) } } /// Gets the rendered value of the specified constant or associated constant. From 2c11c35f8982a9a5fd654f0499cc72b70208d62f Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 11 Jun 2020 13:48:46 -0400 Subject: [PATCH 04/19] Explain move errors that occur due to method calls involving `self` --- src/librustc_ast_lowering/expr.rs | 24 ++- .../infer/error_reporting/need_type_info.rs | 2 +- src/librustc_middle/lint.rs | 4 +- .../diagnostics/conflict_errors.rs | 72 +++++++- .../diagnostics/explain_borrow.rs | 2 +- .../borrow_check/diagnostics/mod.rs | 152 ++++++++++++++--- .../borrow_check/diagnostics/move_errors.rs | 2 +- .../diagnostics/mutability_errors.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 6 + src/librustc_mir/transform/const_prop.rs | 1 + src/librustc_span/hygiene.rs | 13 +- src/librustc_span/lib.rs | 4 +- src/test/ui/binop/binop-consume-args.stderr | 70 ++++++-- src/test/ui/binop/binop-move-semantics.stderr | 21 ++- .../borrowck/borrowck-unboxed-closures.stderr | 7 +- .../ui/closure_context/issue-42065.stderr | 7 +- src/test/ui/codemap_tests/tab_3.stderr | 8 +- .../ui/consts/miri_unleashed/ptr_arith.rs | 5 +- .../ui/consts/miri_unleashed/ptr_arith.stderr | 4 +- src/test/ui/hygiene/unpretty-debug.stdout | 4 + src/test/ui/issues/issue-12127.stderr | 7 +- src/test/ui/issues/issue-33941.rs | 1 + src/test/ui/issues/issue-33941.stderr | 12 +- src/test/ui/issues/issue-34721.stderr | 9 +- src/test/ui/issues/issue-61108.stderr | 8 +- src/test/ui/issues/issue-64559.stderr | 8 +- src/test/ui/moves/move-fn-self-receiver.rs | 74 ++++++++ .../ui/moves/move-fn-self-receiver.stderr | 158 ++++++++++++++++++ ...moves-based-on-type-access-to-field.stderr | 8 +- .../ui/moves/moves-based-on-type-exprs.stderr | 16 +- .../ui/once-cant-call-twice-on-heap.stderr | 7 +- ...ed-closures-infer-fnonce-call-twice.stderr | 7 +- ...osures-infer-fnonce-move-call-twice.stderr | 7 +- src/test/ui/unop-move-semantics.stderr | 7 +- .../unsized-locals/borrow-after-move.stderr | 8 +- src/test/ui/unsized-locals/double-move.stderr | 8 +- .../use-after-move-self-based-on-type.stderr | 8 +- src/test/ui/use/use-after-move-self.stderr | 8 +- src/test/ui/walk-struct-literal-with.stderr | 8 +- 39 files changed, 697 insertions(+), 82 deletions(-) create mode 100644 src/test/ui/moves/move-fn-self-receiver.rs create mode 100644 src/test/ui/moves/move-fn-self-receiver.stderr diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs index b7894eb145b0a..e59cacfffc926 100644 --- a/src/librustc_ast_lowering/expr.rs +++ b/src/librustc_ast_lowering/expr.rs @@ -9,7 +9,7 @@ use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::Res; -use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; +use rustc_span::source_map::{respan, DesugaringKind, ForLoopLoc, Span, Spanned}; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_target::asm; use std::collections::hash_map::Entry; @@ -25,6 +25,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> { + let mut span = e.span; ensure_sufficient_stack(|| { let kind = match e.kind { ExprKind::Box(ref inner) => hir::ExprKind::Box(self.lower_expr(inner)), @@ -53,6 +54,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args, span) } ExprKind::Binary(binop, ref lhs, ref rhs) => { + span = self.mark_span_with_reason(DesugaringKind::Operator, e.span, None); let binop = self.lower_binop(binop); let lhs = self.lower_expr(lhs); let rhs = self.lower_expr(rhs); @@ -222,7 +224,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::Expr { hir_id: self.lower_node_id(e.id), kind, - span: e.span, + span, attrs: e.attrs.iter().map(|a| self.lower_attr(a)).collect::>().into(), } }) @@ -237,6 +239,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_binop(&mut self, b: BinOp) -> hir::BinOp { + let span = self.mark_span_with_reason(DesugaringKind::Operator, b.span, None); Spanned { node: match b.node { BinOpKind::Add => hir::BinOpKind::Add, @@ -258,7 +261,7 @@ impl<'hir> LoweringContext<'_, 'hir> { BinOpKind::Ge => hir::BinOpKind::Ge, BinOpKind::Gt => hir::BinOpKind::Gt, }, - span: b.span, + span, } } @@ -1360,9 +1363,14 @@ impl<'hir> LoweringContext<'_, 'hir> { body: &Block, opt_label: Option