Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 6 pull requests #111680

Merged
merged 16 commits into from
May 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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