Skip to content

Commit

Permalink
Auto merge of rust-lang#111680 - Dylan-DPC:rollup-1p45gxt, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 6 pull requests

Successful merges:

 - rust-lang#110930 (Don't expect normalization to succeed in elaborate_drops)
 - rust-lang#111557 (Revert "Validate resolution for SelfCtor too.")
 - rust-lang#111565 (rustdoc-json: Add tests for visibility of impls)
 - rust-lang#111588 (Emits E0599 when meeting `MyTrait::missing_method`)
 - rust-lang#111625 (Move rustc_middle/src/ty/query.rs to rustc_middle/src/query/plumbing.rs)
 - rust-lang#111674 (Add missing backslash in HTML string)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed May 17, 2023
2 parents c2ccc85 + b0d92c2 commit ad23942
Show file tree
Hide file tree
Showing 40 changed files with 394 additions and 137 deletions.
3 changes: 2 additions & 1 deletion compiler/rustc_const_eval/src/const_eval/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use std::fmt;

use rustc_errors::Diagnostic;
use rustc_middle::mir::AssertKind;
use rustc_middle::ty::{layout::LayoutError, query::TyCtxtAt, ConstInt};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::{layout::LayoutError, ConstInt};
use rustc_span::{Span, Symbol};

use super::InterpCx;
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_const_eval/src/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@ use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
use rustc_index::IndexVec;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{ErrorHandled, InterpError, ReportedErrorInfo};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::layout::{
self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers,
TyAndLayout,
};
use rustc_middle::ty::{
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
};
use rustc_middle::ty::{self, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable};
use rustc_mir_dataflow::storage::always_storage_live_locals;
use rustc_session::Limit;
use rustc_span::Span;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@ pub enum StashKey {
/// FRU syntax
MaybeFruTypo,
CallAssocMethod,
TraitMissingMethod,
}

fn default_track_diagnostic(d: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) {
Expand Down
7 changes: 3 additions & 4 deletions compiler/rustc_hir_analysis/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use rustc_ast::TraitObjectSyntax;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, FatalError,
MultiSpan,
MultiSpan, StashKey,
};
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
Expand All @@ -38,7 +38,6 @@ use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}
use rustc_middle::ty::{DynKind, ToPredicate};
use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::edition::Edition;
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::{sym, Span, DUMMY_SP};
use rustc_target::spec::abi;
Expand Down Expand Up @@ -3718,7 +3717,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
));
}

if self_ty.span.edition() >= Edition::Edition2021 {
if self_ty.span.edition().rust_2021() {
let msg = "trait objects must include the `dyn` keyword";
let label = "add `dyn` keyword before this trait";
let mut diag =
Expand All @@ -3732,7 +3731,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
// check if the impl trait that we are considering is a impl of a local trait
self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag);
diag.emit();
diag.stash(self_ty.span, StashKey::TraitMissingMethod);
} else {
let msg = "trait objects without an explicit `dyn` are deprecated";
tcx.struct_span_lint_hir(
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_hir_typeck/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,14 @@ hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but
hir_typeck_suggest_boxing_note = for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
hir_typeck_suggest_boxing_when_appropriate = store this in the heap by calling `Box::new`
hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method ->
[true] {""}
*[other] {" "}in the current scope
}
hir_typeck_candidate_trait_note = `{$trait_name}` defines an item `{$item_name}`{$action_or_ty ->
[NONE] {""}
[implement] , perhaps you need to implement it
*[other] , perhaps you need to restrict type parameter `{$action_or_ty}` with it
}
24 changes: 24 additions & 0 deletions compiler/rustc_hir_typeck/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
//! Errors emitted by `rustc_hir_typeck`.
use std::borrow::Cow;

use crate::fluent_generated as fluent;
use rustc_errors::{AddToDiagnostic, Applicability, Diagnostic, MultiSpan, SubdiagnosticMessage};
use rustc_macros::{Diagnostic, Subdiagnostic};
Expand Down Expand Up @@ -295,3 +297,25 @@ pub enum SuggestBoxing {
end: Span,
},
}

#[derive(Diagnostic)]
#[diag(hir_typeck_no_associated_item, code = "E0599")]
pub struct NoAssociatedItem {
#[primary_span]
pub span: Span,
pub item_kind: &'static str,
pub item_name: Ident,
pub ty_prefix: Cow<'static, str>,
pub ty_str: String,
pub trait_missing_method: bool,
}

#[derive(Subdiagnostic)]
#[note(hir_typeck_candidate_trait_note)]
pub struct CandidateTraitNote {
#[primary_span]
pub span: Span,
pub trait_name: String,
pub item_name: Ident,
pub action_or_ty: String,
}
1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1245,6 +1245,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
error,
Some((rcvr, args)),
expected,
false,
) {
err.emit();
}
Expand Down
26 changes: 24 additions & 2 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::rvalue_scopes;
use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, RawTy};
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan, StashKey};
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
Expand Down Expand Up @@ -853,6 +853,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let item_name = item_segment.ident;
let result = self
.resolve_fully_qualified_call(span, item_name, ty.normalized, qself.span, hir_id)
.and_then(|r| {
// lint bare trait if the method is found in the trait
if span.edition().rust_2021() && let Some(mut diag) = self.tcx.sess.diagnostic().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) {
diag.emit();
}
Ok(r)
})
.or_else(|error| {
let guar = self
.tcx
Expand All @@ -863,17 +870,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => Err(guar),
};

let trait_missing_method =
matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait();
// If we have a path like `MyTrait::missing_method`, then don't register
// a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise,
// register a WF obligation so that we can detect any additional
// errors in the self type.
if !(matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait()) {
if !trait_missing_method {
self.register_wf_obligation(
ty.raw.into(),
qself.span,
traits::WellFormed(None),
);
}

// emit or cancel the diagnostic for bare traits
if span.edition().rust_2021() && let Some(mut diag) = self.tcx.sess.diagnostic().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) {
if trait_missing_method {
// cancel the diag for bare traits when meeting `MyTrait::missing_method`
diag.cancel();
} else {
diag.emit();
}
}

if item_name.name != kw::Empty {
if let Some(mut e) = self.report_method_error(
span,
Expand All @@ -883,10 +903,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
error,
None,
Expectation::NoExpectation,
trait_missing_method && span.edition().rust_2021(), // emits missing method for trait only after edition 2021
) {
e.emit();
}
}

result
});

Expand Down
85 changes: 55 additions & 30 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
//! found or is otherwise invalid.

use crate::errors;
use crate::errors::CandidateTraitNote;
use crate::errors::NoAssociatedItem;
use crate::Expectation;
use crate::FnCtxt;
use rustc_ast::ast::Mutability;
Expand Down Expand Up @@ -38,6 +40,7 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _
use rustc_trait_selection::traits::{
FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
};
use std::borrow::Cow;

use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
use super::{CandidateSource, MethodError, NoMatchData};
Expand Down Expand Up @@ -112,6 +115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
error: MethodError<'tcx>,
args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
expected: Expectation<'tcx>,
trait_missing_method: bool,
) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
// Avoid suggestions when we don't know what's going on.
if rcvr_ty.references_error() {
Expand All @@ -136,6 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sugg_span,
&mut no_match_data,
expected,
trait_missing_method,
);
}

Expand Down Expand Up @@ -278,6 +283,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sugg_span: Span,
no_match_data: &mut NoMatchData<'tcx>,
expected: Expectation<'tcx>,
trait_missing_method: bool,
) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
let mode = no_match_data.mode;
let tcx = self.tcx;
Expand Down Expand Up @@ -323,7 +329,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span = item_name.span;

// Don't show generic arguments when the method can't be found in any implementation (#81576).
let mut ty_str_reported = ty_str.clone();
let mut ty_str_reported = if trait_missing_method {
ty_str.strip_prefix("dyn ").expect("Failed to remove the prefix dyn").to_owned()
} else {
ty_str.clone()
};

if let ty::Adt(_, generics) = rcvr_ty.kind() {
if generics.len() > 0 {
let mut autoderef = self.autoderef(span, rcvr_ty);
Expand Down Expand Up @@ -355,25 +366,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
self.suggest_missing_writer(rcvr_ty, args)
} else {
struct_span_err!(
tcx.sess,
tcx.sess.create_err(NoAssociatedItem {
span,
E0599,
"no {} named `{}` found for {} `{}` in the current scope",
item_kind,
item_name,
rcvr_ty.prefix_string(self.tcx),
ty_str_reported,
)
ty_prefix: if trait_missing_method {
// FIXME(mu001999) E0599 maybe not suitable here because it is for types
Cow::from("trait")
} else {
rcvr_ty.prefix_string(self.tcx)
},
ty_str: ty_str_reported,
trait_missing_method,
})
};
if tcx.sess.source_map().is_multiline(sugg_span) {
err.span_label(sugg_span.with_hi(span.lo()), "");
}
let ty_str = if short_ty_str.len() < ty_str.len() && ty_str.len() > 10 {
let mut ty_str = if short_ty_str.len() < ty_str.len() && ty_str.len() > 10 {
short_ty_str
} else {
ty_str
};
if trait_missing_method {
ty_str =
ty_str.strip_prefix("dyn ").expect("Failed to remove the prefix dyn").to_owned();
}

if let Some(file) = ty_file {
err.note(format!("the full type name has been written to '{}'", file.display(),));
}
Expand Down Expand Up @@ -1067,6 +1086,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&static_candidates,
unsatisfied_bounds,
expected.only_has_type(self),
trait_missing_method,
);
}

Expand Down Expand Up @@ -2375,6 +2395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
static_candidates: &[CandidateSource],
unsatisfied_bounds: bool,
return_type: Option<Ty<'tcx>>,
trait_missing_method: bool,
) {
let mut alt_rcvr_sugg = false;
if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
Expand Down Expand Up @@ -2598,11 +2619,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
},
_ => None,
};
err.help(if param_type.is_some() {
"items from traits can only be used if the type parameter is bounded by the trait"
} else {
"items from traits can only be used if the trait is implemented and in scope"
});
if !trait_missing_method {
err.help(if param_type.is_some() {
"items from traits can only be used if the type parameter is bounded by the trait"
} else {
"items from traits can only be used if the trait is implemented and in scope"
});
}

let candidates_len = candidates.len();
let message = |action| {
format!(
Expand Down Expand Up @@ -2751,27 +2775,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(candidates, Vec::new())
};

let action = if let Some(param) = param_type {
format!("restrict type parameter `{}` with", param)
} else {
// FIXME: it might only need to be imported into scope, not implemented.
"implement".to_string()
};
match &potential_candidates[..] {
[] => {}
[trait_info] if trait_info.def_id.is_local() => {
err.span_note(
self.tcx.def_span(trait_info.def_id),
format!(
"`{}` defines an item `{}`, perhaps you need to {} it",
self.tcx.def_path_str(trait_info.def_id),
item_name,
action
),
);
err.subdiagnostic(CandidateTraitNote {
span: self.tcx.def_span(trait_info.def_id),
trait_name: self.tcx.def_path_str(trait_info.def_id),
item_name,
action_or_ty: if trait_missing_method {
"NONE".to_string()
} else {
param_type.map_or_else(
|| "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
ToString::to_string,
)
},
});
}
trait_infos => {
let mut msg = message(action);
let mut msg = message(param_type.map_or_else(
|| "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
|param| format!("restrict type parameter `{}` with", param),
));
for (i, trait_info) in trait_infos.iter().enumerate() {
msg.push_str(&format!(
"\ncandidate #{}: `{}`",
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ pub mod middle;
pub mod mir;
pub mod thir;
pub mod traits;
#[macro_use]
pub mod ty;
pub mod util;
mod values;
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_middle/src/mir/interpret/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use super::{AllocId, AllocRange, ConstAlloc, Pointer, Scalar};

use crate::mir::interpret::ConstValue;
use crate::ty::{layout, query::TyCtxtAt, tls, Ty, ValTree};
use crate::query::TyCtxtAt;
use crate::ty::{layout, tls, Ty, ValTree};

use rustc_data_structures::sync::Lock;
use rustc_errors::{pluralize, struct_span_err, DiagnosticBuilder, ErrorGuaranteed};
Expand Down
Loading

0 comments on commit ad23942

Please sign in to comment.