Auto merge of #94431 - matthiaskrgr:rollup-1jsj0wu, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #94396 (1 - Make more use of `let_chains`) - #94397 (Document that pre-expansion lint passes are softly deprecated) - #94399 (Add test for #79465 to prevent regression) - #94409 (avoid rebuilding bootstrap when PATH changes) - #94415 (Use the first codegen backend in the config.toml as default) - #94417 (Fix duplicated impl links) - #94420 (3 - Make more use of `let_chains`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
b07d59f794
@ -1921,17 +1921,16 @@ pub(crate) fn report_illegal_reassignment(
|
||||
err.span_label(assigned_span, format!("first assignment to {}", place_description));
|
||||
}
|
||||
}
|
||||
if let Some(decl) = local_decl {
|
||||
if let Some(name) = local_name {
|
||||
if decl.can_be_made_mutable() {
|
||||
err.span_suggestion(
|
||||
decl.source_info.span,
|
||||
"consider making this binding mutable",
|
||||
format!("mut {}", name),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(decl) = local_decl
|
||||
&& let Some(name) = local_name
|
||||
&& decl.can_be_made_mutable()
|
||||
{
|
||||
err.span_suggestion(
|
||||
decl.source_info.span,
|
||||
"consider making this binding mutable",
|
||||
format!("mut {}", name),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
err.span_label(span, msg);
|
||||
self.buffer_error(err);
|
||||
|
@ -375,15 +375,12 @@ pub(crate) fn explain_why_borrow_contains_point(
|
||||
|
||||
Some(Cause::DropVar(local, location)) => {
|
||||
let mut should_note_order = false;
|
||||
if self.local_names[local].is_some() {
|
||||
if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
|
||||
if let Some(borrowed_local) = place.as_local() {
|
||||
if self.local_names[borrowed_local].is_some() && local != borrowed_local
|
||||
{
|
||||
should_note_order = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.local_names[local].is_some()
|
||||
&& let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place
|
||||
&& let Some(borrowed_local) = place.as_local()
|
||||
&& self.local_names[borrowed_local].is_some() && local != borrowed_local
|
||||
{
|
||||
should_note_order = true;
|
||||
}
|
||||
|
||||
BorrowExplanation::UsedLaterWhenDropped {
|
||||
|
@ -1086,21 +1086,17 @@ fn get_mut_span_in_struct_field<'tcx>(
|
||||
field: &mir::Field,
|
||||
) -> Option<Span> {
|
||||
// Expect our local to be a reference to a struct of some kind.
|
||||
if let ty::Ref(_, ty, _) = ty.kind() {
|
||||
if let ty::Adt(def, _) = ty.kind() {
|
||||
let field = def.all_fields().nth(field.index())?;
|
||||
// Use the HIR types to construct the diagnostic message.
|
||||
let node = tcx.hir().find_by_def_id(field.did.as_local()?)?;
|
||||
// Now we're dealing with the actual struct that we're going to suggest a change to,
|
||||
// we can expect a field that is an immutable reference to a type.
|
||||
if let hir::Node::Field(field) = node {
|
||||
if let hir::TyKind::Rptr(lifetime, hir::MutTy { mutbl: hir::Mutability::Not, ty }) =
|
||||
field.ty.kind
|
||||
{
|
||||
return Some(lifetime.span.between(ty.span));
|
||||
}
|
||||
}
|
||||
}
|
||||
if let ty::Ref(_, ty, _) = ty.kind()
|
||||
&& let ty::Adt(def, _) = ty.kind()
|
||||
&& let field = def.all_fields().nth(field.index())?
|
||||
// Use the HIR types to construct the diagnostic message.
|
||||
&& let node = tcx.hir().find_by_def_id(field.did.as_local()?)?
|
||||
// Now we're dealing with the actual struct that we're going to suggest a change to,
|
||||
// we can expect a field that is an immutable reference to a type.
|
||||
&& let hir::Node::Field(field) = node
|
||||
&& let hir::TyKind::Rptr(lt, hir::MutTy { mutbl: hir::Mutability::Not, ty }) = field.ty.kind
|
||||
{
|
||||
return Some(lt.span.between(ty.span));
|
||||
}
|
||||
|
||||
None
|
||||
|
@ -140,14 +140,11 @@ pub(super) fn to_error_region_vid(&self, r: RegionVid) -> Option<RegionVid> {
|
||||
|
||||
/// Returns `true` if a closure is inferred to be an `FnMut` closure.
|
||||
fn is_closure_fn_mut(&self, fr: RegionVid) -> bool {
|
||||
if let Some(ty::ReFree(free_region)) = self.to_error_region(fr).as_deref() {
|
||||
if let ty::BoundRegionKind::BrEnv = free_region.bound_region {
|
||||
if let DefiningTy::Closure(_, substs) =
|
||||
self.regioncx.universal_regions().defining_ty
|
||||
{
|
||||
return substs.as_closure().kind() == ty::ClosureKind::FnMut;
|
||||
}
|
||||
}
|
||||
if let Some(ty::ReFree(free_region)) = self.to_error_region(fr).as_deref()
|
||||
&& let ty::BoundRegionKind::BrEnv = free_region.bound_region
|
||||
&& let DefiningTy::Closure(_, substs) = self.regioncx.universal_regions().defining_ty
|
||||
{
|
||||
return substs.as_closure().kind() == ty::ClosureKind::FnMut;
|
||||
}
|
||||
|
||||
false
|
||||
|
@ -1,15 +1,16 @@
|
||||
//! This query borrow-checks the MIR to (further) ensure it is not broken.
|
||||
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![feature(bool_to_option)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(let_else)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(trusted_step)]
|
||||
#![feature(try_blocks)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustc_middle;
|
||||
@ -159,16 +160,14 @@ fn do_mir_borrowck<'a, 'tcx>(
|
||||
for var_debug_info in &input_body.var_debug_info {
|
||||
if let VarDebugInfoContents::Place(place) = var_debug_info.value {
|
||||
if let Some(local) = place.as_local() {
|
||||
if let Some(prev_name) = local_names[local] {
|
||||
if var_debug_info.name != prev_name {
|
||||
span_bug!(
|
||||
var_debug_info.source_info.span,
|
||||
"local {:?} has many names (`{}` vs `{}`)",
|
||||
local,
|
||||
prev_name,
|
||||
var_debug_info.name
|
||||
);
|
||||
}
|
||||
if let Some(prev_name) = local_names[local] && var_debug_info.name != prev_name {
|
||||
span_bug!(
|
||||
var_debug_info.source_info.span,
|
||||
"local {:?} has many names (`{}` vs `{}`)",
|
||||
local,
|
||||
prev_name,
|
||||
var_debug_info.name
|
||||
);
|
||||
}
|
||||
local_names[local] = Some(var_debug_info.name);
|
||||
}
|
||||
|
@ -60,10 +60,8 @@ pub(super) fn borrow_conflicts_with_place<'tcx>(
|
||||
|
||||
// This Local/Local case is handled by the more general code below, but
|
||||
// it's so common that it's a speed win to check for it first.
|
||||
if let Some(l1) = borrow_place.as_local() {
|
||||
if let Some(l2) = access_place.as_local() {
|
||||
return l1 == l2;
|
||||
}
|
||||
if let Some(l1) = borrow_place.as_local() && let Some(l2) = access_place.as_local() {
|
||||
return l1 == l2;
|
||||
}
|
||||
|
||||
place_components_conflict(tcx, body, borrow_place, borrow_kind, access_place, access, bias)
|
||||
|
@ -236,13 +236,9 @@ pub fn get_codegen_backend(
|
||||
static LOAD: SyncOnceCell<unsafe fn() -> Box<dyn CodegenBackend>> = SyncOnceCell::new();
|
||||
|
||||
let load = LOAD.get_or_init(|| {
|
||||
#[cfg(feature = "llvm")]
|
||||
const DEFAULT_CODEGEN_BACKEND: &str = "llvm";
|
||||
let default_codegen_backend = option_env!("CFG_DEFAULT_CODEGEN_BACKEND").unwrap_or("llvm");
|
||||
|
||||
#[cfg(not(feature = "llvm"))]
|
||||
const DEFAULT_CODEGEN_BACKEND: &str = "cranelift";
|
||||
|
||||
match backend_name.unwrap_or(DEFAULT_CODEGEN_BACKEND) {
|
||||
match backend_name.unwrap_or(default_codegen_backend) {
|
||||
filename if filename.contains('.') => load_backend_from_dylib(filename.as_ref()),
|
||||
#[cfg(feature = "llvm")]
|
||||
"llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new,
|
||||
|
@ -166,7 +166,12 @@ pub fn register_early_pass(
|
||||
self.early_passes.push(Box::new(pass));
|
||||
}
|
||||
|
||||
/// Used by clippy.
|
||||
/// This lint pass is softly deprecated. It misses expanded code and has caused a few
|
||||
/// errors in the past. Currently, it is only used in Clippy. New implementations
|
||||
/// should avoid using this interface, as it might be removed in the future.
|
||||
///
|
||||
/// * See [rust#69838](https://github.com/rust-lang/rust/pull/69838)
|
||||
/// * See [rust-clippy#5518](https://github.com/rust-lang/rust-clippy/pull/5518)
|
||||
pub fn register_pre_expansion_pass(
|
||||
&mut self,
|
||||
pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync,
|
||||
|
@ -1054,12 +1054,11 @@ pub(crate) fn compute_bounds_that_match_assoc_type(
|
||||
let mut result = Vec::new();
|
||||
|
||||
for ast_bound in ast_bounds {
|
||||
if let Some(trait_ref) = ast_bound.trait_ref() {
|
||||
if let Some(trait_did) = trait_ref.trait_def_id() {
|
||||
if self.tcx().trait_may_define_assoc_type(trait_did, assoc_name) {
|
||||
result.push(ast_bound.clone());
|
||||
}
|
||||
}
|
||||
if let Some(trait_ref) = ast_bound.trait_ref()
|
||||
&& let Some(trait_did) = trait_ref.trait_def_id()
|
||||
&& self.tcx().trait_may_define_assoc_type(trait_did, assoc_name)
|
||||
{
|
||||
result.push(ast_bound.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,13 +282,12 @@ pub(super) fn check_fn<'a, 'tcx>(
|
||||
sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`");
|
||||
}
|
||||
|
||||
if let Node::Item(item) = hir.get(fn_id) {
|
||||
if let ItemKind::Fn(_, ref generics, _) = item.kind {
|
||||
if !generics.params.is_empty() {
|
||||
if let Node::Item(item) = hir.get(fn_id)
|
||||
&& let ItemKind::Fn(_, ref generics, _) = item.kind
|
||||
&& !generics.params.is_empty()
|
||||
{
|
||||
sess.span_err(span, "should have no type parameters");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let span = sess.source_map().guess_head_span(span);
|
||||
sess.span_err(span, "function should have one argument");
|
||||
@ -319,17 +318,15 @@ pub(super) fn check_fn<'a, 'tcx>(
|
||||
sess.span_err(decl.inputs[0].span, "argument should be `Layout`");
|
||||
}
|
||||
|
||||
if let Node::Item(item) = hir.get(fn_id) {
|
||||
if let ItemKind::Fn(_, ref generics, _) = item.kind {
|
||||
if !generics.params.is_empty() {
|
||||
if let Node::Item(item) = hir.get(fn_id)
|
||||
&& let ItemKind::Fn(_, ref generics, _) = item.kind
|
||||
&& !generics.params.is_empty()
|
||||
{
|
||||
sess.span_err(
|
||||
span,
|
||||
"`#[alloc_error_handler]` function should have no type \
|
||||
parameters",
|
||||
"`#[alloc_error_handler]` function should have no type parameters",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let span = sess.source_map().guess_head_span(span);
|
||||
sess.span_err(span, "function should have one argument");
|
||||
@ -1146,9 +1143,10 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: &ty::AdtDef) {
|
||||
if repr.packed() {
|
||||
for attr in tcx.get_attrs(def.did).iter() {
|
||||
for r in attr::find_repr_attrs(&tcx.sess, attr) {
|
||||
if let attr::ReprPacked(pack) = r {
|
||||
if let Some(repr_pack) = repr.pack {
|
||||
if pack as u64 != repr_pack.bytes() {
|
||||
if let attr::ReprPacked(pack) = r
|
||||
&& let Some(repr_pack) = repr.pack
|
||||
&& pack as u64 != repr_pack.bytes()
|
||||
{
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
sp,
|
||||
@ -1156,8 +1154,6 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: &ty::AdtDef) {
|
||||
"type has conflicting packed representation hints"
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1399,12 +1395,11 @@ fn display_discriminant_value<'tcx>(
|
||||
) -> String {
|
||||
if let Some(expr) = &variant.disr_expr {
|
||||
let body = &tcx.hir().body(expr.body).value;
|
||||
if let hir::ExprKind::Lit(lit) = &body.kind {
|
||||
if let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node {
|
||||
if evaluated != *lit_value {
|
||||
if let hir::ExprKind::Lit(lit) = &body.kind
|
||||
&& let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node
|
||||
&& evaluated != *lit_value
|
||||
{
|
||||
return format!("`{}` (overflowed from `{}`)", evaluated, lit_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
format!("`{}`", evaluated)
|
||||
|
@ -1696,13 +1696,12 @@ fn add_impl_trait_explanation<'a>(
|
||||
}
|
||||
|
||||
fn is_return_ty_unsized<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool {
|
||||
if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id) {
|
||||
if let hir::FnRetTy::Return(ty) = fn_decl.output {
|
||||
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(fcx, ty);
|
||||
if let ty::Dynamic(..) = ty.kind() {
|
||||
if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id)
|
||||
&& let hir::FnRetTy::Return(ty) = fn_decl.output
|
||||
&& let ty = <dyn AstConv<'_>>::ast_ty_to_ty(fcx, ty)
|
||||
&& let ty::Dynamic(..) = ty.kind()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
@ -587,9 +587,10 @@ pub fn check_ref(
|
||||
match (&expr.kind, expected.kind(), checked_ty.kind()) {
|
||||
(_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (exp.kind(), check.kind()) {
|
||||
(&ty::Str, &ty::Array(arr, _) | &ty::Slice(arr)) if arr == self.tcx.types.u8 => {
|
||||
if let hir::ExprKind::Lit(_) = expr.kind {
|
||||
if let Ok(src) = sm.span_to_snippet(sp) {
|
||||
if replace_prefix(&src, "b\"", "\"").is_some() {
|
||||
if let hir::ExprKind::Lit(_) = expr.kind
|
||||
&& let Ok(src) = sm.span_to_snippet(sp)
|
||||
&& replace_prefix(&src, "b\"", "\"").is_some()
|
||||
{
|
||||
let pos = sp.lo() + BytePos(1);
|
||||
return Some((
|
||||
sp.with_hi(pos),
|
||||
@ -600,12 +601,11 @@ pub fn check_ref(
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(&ty::Array(arr, _) | &ty::Slice(arr), &ty::Str) if arr == self.tcx.types.u8 => {
|
||||
if let hir::ExprKind::Lit(_) = expr.kind {
|
||||
if let Ok(src) = sm.span_to_snippet(sp) {
|
||||
if replace_prefix(&src, "\"", "b\"").is_some() {
|
||||
if let hir::ExprKind::Lit(_) = expr.kind
|
||||
&& let Ok(src) = sm.span_to_snippet(sp)
|
||||
&& replace_prefix(&src, "\"", "b\"").is_some()
|
||||
{
|
||||
return Some((
|
||||
sp.shrink_to_lo(),
|
||||
"consider adding a leading `b`",
|
||||
@ -613,8 +613,7 @@ pub fn check_ref(
|
||||
Applicability::MachineApplicable,
|
||||
true,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -810,10 +810,8 @@ pub(super) fn check_return_expr(
|
||||
// Use the span of the trailing expression for our cause,
|
||||
// not the span of the entire function
|
||||
if !explicit_return {
|
||||
if let ExprKind::Block(body, _) = return_expr.kind {
|
||||
if let Some(last_expr) = body.expr {
|
||||
span = last_expr.span;
|
||||
}
|
||||
if let ExprKind::Block(body, _) = return_expr.kind && let Some(last_expr) = body.expr {
|
||||
span = last_expr.span;
|
||||
}
|
||||
}
|
||||
ret_coercion.borrow_mut().coerce(
|
||||
|
@ -402,25 +402,23 @@ pub(in super::super) fn check_argument_types(
|
||||
if arg_count == 0 || i + 1 == arg_count { &label } else { "" },
|
||||
);
|
||||
}
|
||||
if let Some(def_id) = fn_def_id {
|
||||
if let Some(def_span) = tcx.def_ident_span(def_id) {
|
||||
let mut spans: MultiSpan = def_span.into();
|
||||
if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
|
||||
let mut spans: MultiSpan = def_span.into();
|
||||
|
||||
let params = tcx
|
||||
.hir()
|
||||
.get_if_local(def_id)
|
||||
.and_then(|node| node.body_id())
|
||||
.into_iter()
|
||||
.map(|id| tcx.hir().body(id).params)
|
||||
.flatten();
|
||||
let params = tcx
|
||||
.hir()
|
||||
.get_if_local(def_id)
|
||||
.and_then(|node| node.body_id())
|
||||
.into_iter()
|
||||
.map(|id| tcx.hir().body(id).params)
|
||||
.flatten();
|
||||
|
||||
for param in params {
|
||||
spans.push_span_label(param.span, String::new());
|
||||
}
|
||||
|
||||
let def_kind = tcx.def_kind(def_id);
|
||||
err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
|
||||
for param in params {
|
||||
spans.push_span_label(param.span, String::new());
|
||||
}
|
||||
|
||||
let def_kind = tcx.def_kind(def_id);
|
||||
err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
|
||||
}
|
||||
if sugg_unit {
|
||||
let sugg_span = tcx.sess.source_map().end_point(call_expr.span);
|
||||
|
@ -430,12 +430,10 @@ pub fn report_method_error(
|
||||
actual.prefix_string(self.tcx),
|
||||
ty_str_reported,
|
||||
);
|
||||
if let Mode::MethodCall = mode {
|
||||
if let SelfSource::MethodCall(call) = source {
|
||||
self.suggest_await_before_method(
|
||||
&mut err, item_name, actual, call, span,
|
||||
);
|
||||
}
|
||||
if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
|
||||
self.suggest_await_before_method(
|
||||
&mut err, item_name, actual, cal, span,
|
||||
);
|
||||
}
|
||||
if let Some(span) =
|
||||
tcx.resolutions(()).confused_type_with_std_module.get(&span)
|
||||
@ -1525,43 +1523,41 @@ fn suggest_traits_to_import(
|
||||
(self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
|
||||
(self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
|
||||
] {
|
||||
if let Some(new_rcvr_t) = *rcvr_ty {
|
||||
if let Ok(pick) = self.lookup_probe(
|
||||
span,
|
||||
item_name,
|
||||
new_rcvr_t,
|
||||
rcvr,
|
||||
crate::check::method::probe::ProbeScope::AllTraits,
|
||||
) {
|
||||
debug!("try_alt_rcvr: pick candidate {:?}", pick);
|
||||
let did = Some(pick.item.container.id());
|
||||
// We don't want to suggest a container type when the missing
|
||||
// method is `.clone()` or `.deref()` otherwise we'd suggest
|
||||
// `Arc::new(foo).clone()`, which is far from what the user wants.
|
||||
// Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
|
||||
// implement the `AsRef` trait.
|
||||
let skip = skippable.contains(&did)
|
||||
|| (("Pin::new" == *pre) && (sym::as_ref == item_name.name));
|
||||
// Make sure the method is defined for the *actual* receiver: we don't
|
||||
// want to treat `Box<Self>` as a receiver if it only works because of
|
||||
// an autoderef to `&self`
|
||||
if pick.autoderefs == 0 && !skip {
|
||||
err.span_label(
|
||||
pick.item.ident(self.tcx).span,
|
||||
&format!("the method is available for `{}` here", new_rcvr_t),
|
||||
);
|
||||
err.multipart_suggestion(
|
||||
"consider wrapping the receiver expression with the \
|
||||
appropriate type",
|
||||
vec![
|
||||
(rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
|
||||
(rcvr.span.shrink_to_hi(), ")".to_string()),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
// We don't care about the other suggestions.
|
||||
alt_rcvr_sugg = true;
|
||||
}
|
||||
if let Some(new_rcvr_t) = *rcvr_ty && let Ok(pick) = self.lookup_probe(
|
||||
span,
|
||||
item_name,
|
||||
new_rcvr_t,
|
||||
rcvr,
|
||||
crate::check::method::probe::ProbeScope::AllTraits,
|
||||
) {
|
||||
debug!("try_alt_rcvr: pick candidate {:?}", pick);
|
||||
let did = Some(pick.item.container.id());
|
||||
// We don't want to suggest a container type when the missing
|
||||
// method is `.clone()` or `.deref()` otherwise we'd suggest
|
||||
// `Arc::new(foo).clone()`, which is far from what the user wants.
|
||||
// Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
|
||||
// implement the `AsRef` trait.
|
||||
let skip = skippable.contains(&did)
|
||||
|| (("Pin::new" == *pre) && (sym::as_ref == item_name.name));
|
||||
// Make sure the method is defined for the *actual* receiver: we don't
|
||||
// want to treat `Box<Self>` as a receiver if it only works because of
|
||||
// an autoderef to `&self`
|
||||
if pick.autoderefs == 0 && !skip {
|
||||
err.span_label(
|
||||
pick.item.ident(self.tcx).span,
|
||||
&format!("the method is available for `{}` here", new_rcvr_t),
|
||||
);
|
||||
err.multipart_suggestion(
|
||||
"consider wrapping the receiver expression with the \
|
||||
appropriate type",
|
||||
vec![
|
||||
(rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
|
||||
(rcvr.span.shrink_to_hi(), ")".to_string()),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
// We don't care about the other suggestions.
|
||||
alt_rcvr_sugg = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -685,9 +685,10 @@ fn borrow_pat_suggestion(
|
||||
}
|
||||
|
||||
pub fn check_dereferenceable(&self, span: Span, expected: Ty<'tcx>, inner: &Pat<'_>) -> bool {
|
||||
if let PatKind::Binding(..) = inner.kind {
|
||||
if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {
|
||||
if let ty::Dynamic(..) = mt.ty.kind() {
|
||||
if let PatKind::Binding(..) = inner.kind
|
||||
&& let Some(mt) = self.shallow_resolve(expected).builtin_deref(true)
|
||||
&& let ty::Dynamic(..) = mt.ty.kind()
|
||||
{
|
||||
// This is "x = SomeTrait" being reduced from
|
||||
// "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
|
||||
let type_str = self.ty_to_string(expected);
|
||||
@ -705,8 +706,6 @@ pub fn check_dereferenceable(&self, span: Span, expected: Ty<'tcx>, inner: &Pat<
|
||||
err.emit();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -190,25 +190,23 @@ struct CollectItemTypesVisitor<'tcx> {
|
||||
let mut is_fn = false;
|
||||
let mut is_const_or_static = false;
|
||||
|
||||
if let Some(hir_ty) = hir_ty {
|
||||
if let hir::TyKind::BareFn(_) = hir_ty.kind {
|
||||
is_fn = true;
|
||||
if let Some(hir_ty) = hir_ty && let hir::TyKind::BareFn(_) = hir_ty.kind {
|
||||
is_fn = true;
|
||||
|
||||
// Check if parent is const or static
|
||||
let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id);
|
||||
let parent_node = tcx.hir().get(parent_id);
|
||||
// Check if parent is const or static
|
||||
let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id);
|
||||
let parent_node = tcx.hir().get(parent_id);
|
||||
|
||||
is_const_or_static = matches!(
|
||||
parent_node,
|
||||
Node::Item(&hir::Item {
|
||||
kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..),
|
||||
..
|
||||
}) | Node::TraitItem(&hir::TraitItem {
|
||||
kind: hir::TraitItemKind::Const(..),
|
||||
..
|
||||
}) | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. })
|
||||
);
|
||||
}
|
||||
is_const_or_static = matches!(
|
||||
parent_node,
|
||||
Node::Item(&hir::Item {
|
||||
kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..),
|
||||
..
|
||||
}) | Node::TraitItem(&hir::TraitItem {
|
||||
kind: hir::TraitItemKind::Const(..),
|
||||
..
|
||||
}) | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. })
|
||||
);
|
||||
}
|
||||
|
||||
// if function is wrapped around a const or static,
|
||||
@ -2417,16 +2415,14 @@ fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::AnonConst
|
||||
let node = tcx.hir().get(hir_id);
|
||||
|
||||
let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() };
|
||||
if let hir::Node::Item(item) = node {
|
||||
if let hir::ItemKind::Impl(ref impl_) = item.kind {
|
||||
if let Some(of_trait) = &impl_.of_trait {
|
||||
debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id);
|
||||
collector.visit_trait_ref(of_trait);
|
||||
}
|
||||
|
||||
debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id);
|
||||
collector.visit_ty(impl_.self_ty);
|
||||
if let hir::Node::Item(item) = node && let hir::ItemKind::Impl(ref impl_) = item.kind {
|
||||
if let Some(of_trait) = &impl_.of_trait {
|
||||
debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id);
|
||||
collector.visit_trait_ref(of_trait);
|
||||
}
|
||||
|
||||
debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id);
|
||||
collector.visit_ty(impl_.self_ty);
|
||||
}
|
||||
|
||||
if let Some(generics) = node.generics() {
|
||||
@ -3280,15 +3276,14 @@ fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, id: DefId) -> &'tcx FxHashSet<Sy
|
||||
/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
|
||||
/// applied to the method prototype.
|
||||
fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||
if let Some(impl_item) = tcx.opt_associated_item(def_id) {
|
||||
if let ty::AssocItemContainer::ImplContainer(_) = impl_item.container {
|
||||
if let Some(trait_item) = impl_item.trait_item_def_id {
|
||||
return tcx
|
||||
.codegen_fn_attrs(trait_item)
|
||||
.flags
|
||||
.intersects(CodegenFnAttrFlags::TRACK_CALLER);
|
||||
}
|
||||
}
|
||||
if let Some(impl_item) = tcx.opt_associated_item(def_id)
|
||||
&& let ty::AssocItemContainer::ImplContainer(_) = impl_item.container
|
||||
&& let Some(trait_item) = impl_item.trait_item_def_id
|
||||
{
|
||||
return tcx
|
||||
.codegen_fn_attrs(trait_item)
|
||||
.flags
|
||||
.intersects(CodegenFnAttrFlags::TRACK_CALLER);
|
||||
}
|
||||
|
||||
false
|
||||
|
@ -55,22 +55,23 @@
|
||||
|
||||
*/
|
||||
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![feature(bool_to_option)]
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(hash_drain_filter)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(is_sorted)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(let_else)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(nll)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(never_type)]
|
||||
#![feature(slice_partition_dedup)]
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(hash_drain_filter)]
|
||||
#![feature(nll)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(slice_partition_dedup)]
|
||||
#![feature(try_blocks)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
@ -304,13 +304,12 @@ pub fn check_explicit_predicates<'tcx>(
|
||||
// = X` binding from the object type (there must be such a
|
||||
// binding) and thus infer an outlives requirement that `X:
|
||||
// 'b`.
|
||||
if let Some(self_ty) = ignored_self_ty {
|
||||
if let GenericArgKind::Type(ty) = outlives_predicate.0.unpack() {
|
||||
if ty.walk().any(|arg| arg == self_ty.into()) {
|
||||
debug!("skipping self ty = {:?}", &ty);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if let Some(self_ty) = ignored_self_ty
|
||||
&& let GenericArgKind::Type(ty) = outlives_predicate.0.unpack()
|
||||
&& ty.walk().any(|arg| arg == self_ty.into())
|
||||
{
|
||||
debug!("skipping self ty = {:?}", &ty);
|
||||
continue;
|
||||
}
|
||||
|
||||
let predicate = outlives_predicate.subst(tcx, substs);
|
||||
|
@ -551,7 +551,9 @@ changelog-seen = 2
|
||||
|
||||
# This is an array of the codegen backends that will be compiled for the rustc
|
||||
# that's being compiled. The default is to only build the LLVM codegen backend,
|
||||
# and currently the only standard options supported are `"llvm"` and `"cranelift"`.
|
||||
# and currently the only standard options supported are `"llvm"`, `"cranelift"`
|
||||
# and `"gcc"`. The first backend in this list will be used as default by rustc
|
||||
# when no explicit backend is specified.
|
||||
#codegen-backends = ["llvm"]
|
||||
|
||||
# Indicates whether LLD will be compiled and made available in the sysroot for
|
||||
|
@ -4,13 +4,13 @@
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-env-changed=RUSTC");
|
||||
println!("cargo:rerun-if-env-changed=PATH");
|
||||
println!("cargo:rustc-env=BUILD_TRIPLE={}", env::var("HOST").unwrap());
|
||||
|
||||
// This may not be a canonicalized path.
|
||||
let mut rustc = PathBuf::from(env::var_os("RUSTC").unwrap());
|
||||
|
||||
if rustc.is_relative() {
|
||||
println!("cargo:rerun-if-env-changed=PATH");
|
||||
for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
|
||||
let absolute = dir.join(&rustc);
|
||||
if absolute.exists() {
|
||||
|
@ -662,6 +662,10 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
|
||||
.env("CFG_RELEASE_CHANNEL", &builder.config.channel)
|
||||
.env("CFG_VERSION", builder.rust_version());
|
||||
|
||||
if let Some(backend) = builder.config.rust_codegen_backends.get(0) {
|
||||
cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend);
|
||||
}
|
||||
|
||||
let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
|
||||
let target_config = builder.config.target_config.get(&target);
|
||||
|
||||
|
@ -74,7 +74,7 @@
|
||||
PrintWithSpace,
|
||||
};
|
||||
use crate::html::highlight;
|
||||
use crate::html::markdown::{HeadingOffset, Markdown, MarkdownHtml, MarkdownSummaryLine};
|
||||
use crate::html::markdown::{HeadingOffset, IdMap, Markdown, MarkdownHtml, MarkdownSummaryLine};
|
||||
use crate::html::sources;
|
||||
use crate::scrape_examples::{CallData, CallLocation};
|
||||
use crate::try_none;
|
||||
@ -1950,8 +1950,10 @@ fn small_url_encode(s: String) -> String {
|
||||
fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
|
||||
let did = it.def_id.expect_def_id();
|
||||
let cache = cx.cache();
|
||||
|
||||
if let Some(v) = cache.impls.get(&did) {
|
||||
let mut used_links = FxHashSet::default();
|
||||
let mut id_map = IdMap::new();
|
||||
|
||||
{
|
||||
let used_links_bor = &mut used_links;
|
||||
@ -1992,7 +1994,7 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
|
||||
sidebar_deref_methods(cx, out, impl_, v, &mut derefs);
|
||||
}
|
||||
|
||||
let format_impls = |impls: Vec<&Impl>| {
|
||||
let format_impls = |impls: Vec<&Impl>, id_map: &mut IdMap| {
|
||||
let mut links = FxHashSet::default();
|
||||
|
||||
let mut ret = impls
|
||||
@ -2001,13 +2003,14 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
|
||||
if let Some(ref i) = it.inner_impl().trait_ {
|
||||
let i_display = format!("{:#}", i.print(cx));
|
||||
let out = Escape(&i_display);
|
||||
let encoded = small_url_encode(format!("{:#}", i.print(cx)));
|
||||
let encoded =
|
||||
id_map.derive(small_url_encode(format!("impl-{:#}", i.print(cx))));
|
||||
let prefix = match it.inner_impl().polarity {
|
||||
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
|
||||
ty::ImplPolarity::Negative => "!",
|
||||
};
|
||||
let generated =
|
||||
format!("<a href=\"#impl-{}\">{}{}</a>", encoded, prefix, out);
|
||||
format!("<a href=\"#{}\">{}{}</a>", encoded, prefix, out);
|
||||
if links.insert(generated.clone()) { Some(generated) } else { None }
|
||||
} else {
|
||||
None
|
||||
@ -2023,9 +2026,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
|
||||
let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) =
|
||||
concrete.into_iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_blanket());
|
||||
|
||||
let concrete_format = format_impls(concrete);
|
||||
let synthetic_format = format_impls(synthetic);
|
||||
let blanket_format = format_impls(blanket_impl);
|
||||
let concrete_format = format_impls(concrete, &mut id_map);
|
||||
let synthetic_format = format_impls(synthetic, &mut id_map);
|
||||
let blanket_format = format_impls(blanket_impl, &mut id_map);
|
||||
|
||||
if !concrete_format.is_empty() {
|
||||
print_sidebar_block(
|
||||
|
3
src/test/rustdoc-ui/issue-79465.rs
Normal file
3
src/test/rustdoc-ui/issue-79465.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub fn f1<T>(x: T::A) {}
|
||||
//~^ ERROR
|
||||
//~^^ ERROR
|
15
src/test/rustdoc-ui/issue-79465.stderr
Normal file
15
src/test/rustdoc-ui/issue-79465.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error[E0220]: associated type `A` not found for `T`
|
||||
--> $DIR/issue-79465.rs:1:20
|
||||
|
|
||||
LL | pub fn f1<T>(x: T::A) {}
|
||||
| ^ associated type `A` not found
|
||||
|
||||
error[E0220]: associated type `A` not found for `T`
|
||||
--> $DIR/issue-79465.rs:1:20
|
||||
|
|
||||
LL | pub fn f1<T>(x: T::A) {}
|
||||
| ^ associated type `A` not found
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0220`.
|
20
src/test/rustdoc/issue-78701.rs
Normal file
20
src/test/rustdoc/issue-78701.rs
Normal file
@ -0,0 +1,20 @@
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// This test ensures that if a blanket impl has the same ID as another impl, it'll
|
||||
// link to the blanket impl and not the other impl. Basically, we're checking if
|
||||
// the ID is correctly derived.
|
||||
|
||||
// @has 'foo/struct.AnotherStruct.html'
|
||||
// @count - '//*[@class="sidebar"]//a[@href="#impl-AnAmazingTrait"]' 1
|
||||
// @count - '//*[@class="sidebar"]//a[@href="#impl-AnAmazingTrait-1"]' 1
|
||||
|
||||
pub trait Something {}
|
||||
|
||||
pub trait AnAmazingTrait {}
|
||||
|
||||
impl<T: Something> AnAmazingTrait for T {}
|
||||
|
||||
pub struct AnotherStruct<T>(T);
|
||||
|
||||
impl<T: Something> Something for AnotherStruct<T> {}
|
||||
impl AnAmazingTrait for AnotherStruct<()> {}
|
Loading…
Reference in New Issue
Block a user