Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
5ed1787
Implement `Ready::into_inner()`
daxpedda Aug 30, 2022
fa61678
Fix leaking in inplace collection when destructor panics
SkiFire13 Sep 10, 2022
f81b07e
Adapt inplace collection leak test to check for no leaks
SkiFire13 Sep 10, 2022
f52082f
Update documentation
SkiFire13 Sep 10, 2022
dad049c
Update test
SkiFire13 Sep 10, 2022
c7d1ec0
Don't ICE when trying to copy unsized value in const prop
compiler-errors Oct 2, 2022
d0d6af9
Lint for unsatisfied nested opaques
compiler-errors Oct 2, 2022
426424b
Make it a lint for all opaque types
compiler-errors Oct 2, 2022
7a88540
Add example to opaque_hidden_inferred_bound lint
compiler-errors Oct 2, 2022
1750c7b
Clarify documentation
SkiFire13 Sep 10, 2022
1456f73
Fix rustdoc ICE in invalid_rust_codeblocks lint
Noratrieb Oct 3, 2022
8c60012
Normalize substs before resolving instance in NoopMethodCall lint
compiler-errors Sep 29, 2022
e1b313a
We are able to resolve methods even if they need subst
compiler-errors Oct 4, 2022
c1d4003
Rollup merge of #101189 - daxpedda:ready-into-inner, r=joshtriplett
Dylan-DPC Oct 4, 2022
f24d00d
Rollup merge of #101642 - SkiFire13:fix-inplace-collection-leak, r=th…
Dylan-DPC Oct 4, 2022
d89d214
Rollup merge of #102489 - compiler-errors:issue-102074, r=oli-obk
Dylan-DPC Oct 4, 2022
32dde23
Rollup merge of #102559 - compiler-errors:issue-102553, r=oli-obk
Dylan-DPC Oct 4, 2022
35f92ed
Rollup merge of #102568 - compiler-errors:lint-unsatisfied-opaques, r…
Dylan-DPC Oct 4, 2022
f7ca465
Rollup merge of #102633 - Nilstrieb:rustdoc-lint-🏳️‍⚧️late, r=davidtwco
Dylan-DPC Oct 4, 2022
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
Prev Previous commit
Next Next commit
Lint for unsatisfied nested opaques
  • Loading branch information
compiler-errors committed Oct 2, 2022
commit d0d6af91467ef60f12396f5d40a09eb4de8cb8b7
4 changes: 4 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/lint.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -433,3 +433,7 @@ lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}`
lint_check_name_warning = {$msg}

lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name}

lint_rpit_hidden_inferred_bound = return-position `{$ty}` does not satisfy its associated type bounds
.specifically = this associated type bound is unsatisfied for `{$proj_ty}`
.suggestion = add this bound
3 changes: 3 additions & 0 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ mod noop_method_call;
mod pass_by_value;
mod passes;
mod redundant_semicolon;
mod rpit_hidden_inferred_bound;
mod traits;
mod types;
mod unused;
Expand Down Expand Up @@ -95,6 +96,7 @@ use nonstandard_style::*;
use noop_method_call::*;
use pass_by_value::*;
use redundant_semicolon::*;
use rpit_hidden_inferred_bound::*;
use traits::*;
use types::*;
use unused::*;
Expand Down Expand Up @@ -223,6 +225,7 @@ macro_rules! late_lint_mod_passes {
EnumIntrinsicsNonEnums: EnumIntrinsicsNonEnums,
InvalidAtomicOrdering: InvalidAtomicOrdering,
NamedAsmLabels: NamedAsmLabels,
RpitHiddenInferredBound: RpitHiddenInferredBound,
]
);
};
Expand Down
143 changes: 143 additions & 0 deletions compiler/rustc_lint/src/rpit_hidden_inferred_bound.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
use hir::def_id::LocalDefId;
use rustc_hir as hir;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_macros::LintDiagnostic;
use rustc_middle::ty::{
self, fold::BottomUpFolder, Ty, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
use rustc_span::Span;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;

use crate::{LateContext, LateLintPass, LintContext};

declare_lint! {
/// The `rpit_hidden_inferred_bound` lint detects cases in which nested RPITs
/// in associated type bounds are not written generally enough to satisfy the
/// bounds of the associated type. This functionality was removed in #97346,
/// but then rolled back in #99860 because it was made into a hard error too
/// quickly.
///
/// We plan on reintroducing this as a hard error, but in the mean time, this
/// lint serves to warn and suggest fixes for any use-cases which rely on this
/// behavior.
pub RPIT_HIDDEN_INFERRED_BOUND,
Warn,
"detects the use of nested RPITs in associated type bounds that are not general enough"
}

declare_lint_pass!(RpitHiddenInferredBound => [RPIT_HIDDEN_INFERRED_BOUND]);

impl<'tcx> LateLintPass<'tcx> for RpitHiddenInferredBound {
fn check_fn(
&mut self,
cx: &LateContext<'tcx>,
kind: hir::intravisit::FnKind<'tcx>,
_: &'tcx hir::FnDecl<'tcx>,
_: &'tcx hir::Body<'tcx>,
_: rustc_span::Span,
id: hir::HirId,
) {
if matches!(kind, hir::intravisit::FnKind::Closure) {
return;
}

let fn_def_id = cx.tcx.hir().local_def_id(id);
let sig: ty::FnSig<'tcx> =
cx.tcx.liberate_late_bound_regions(fn_def_id.to_def_id(), cx.tcx.fn_sig(fn_def_id));
cx.tcx.infer_ctxt().enter(|ref infcx| {
sig.output().visit_with(&mut VisitOpaqueBounds { infcx, cx, fn_def_id });
});
}
}

struct VisitOpaqueBounds<'a, 'cx, 'tcx> {
infcx: &'a InferCtxt<'a, 'tcx>,
cx: &'cx LateContext<'tcx>,
fn_def_id: LocalDefId,
}

impl<'tcx> TypeVisitor<'tcx> for VisitOpaqueBounds<'_, '_, 'tcx> {
fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
if let ty::Opaque(def_id, substs) = *ty.kind()
&& let Some(hir::Node::Item(item)) = self.cx.tcx.hir().get_if_local(def_id)
&& let hir::ItemKind::OpaqueTy(opaque) = &item.kind
&& let hir::OpaqueTyOrigin::FnReturn(origin_def_id) = opaque.origin
&& origin_def_id == self.fn_def_id
{
for pred_and_span in self.cx.tcx.bound_explicit_item_bounds(def_id).transpose_iter() {
let pred_span = pred_and_span.0.1;
let predicate = self.cx.tcx.liberate_late_bound_regions(
def_id,
pred_and_span.map_bound(|(pred, _)| *pred).subst(self.cx.tcx, substs).kind(),
);
let ty::PredicateKind::Projection(proj) = predicate else {
continue;
};
let Some(proj_term) = proj.term.ty() else { continue };

let proj_ty = self
.cx
.tcx
.mk_projection(proj.projection_ty.item_def_id, proj.projection_ty.substs);
let proj_replacer = &mut BottomUpFolder {
tcx: self.cx.tcx,
ty_op: |ty| if ty == proj_ty { proj_term } else { ty },
lt_op: |lt| lt,
ct_op: |ct| ct,
};
for assoc_pred_and_span in self
.cx
.tcx
.bound_explicit_item_bounds(proj.projection_ty.item_def_id)
.transpose_iter()
{
let assoc_pred_span = assoc_pred_and_span.0.1;
let assoc_pred = assoc_pred_and_span
.map_bound(|(pred, _)| *pred)
.subst(self.cx.tcx, &proj.projection_ty.substs)
.fold_with(proj_replacer);
if !self.infcx.predicate_must_hold_modulo_regions(&traits::Obligation::new(
traits::ObligationCause::dummy(),
self.cx.param_env,
assoc_pred,
)) {
let (suggestion, suggest_span) =
match (proj_term.kind(), assoc_pred.kind().skip_binder()) {
(ty::Opaque(def_id, _), ty::PredicateKind::Trait(trait_pred)) => (
format!(" + {}", trait_pred.print_modifiers_and_trait_path()),
Some(self.cx.tcx.def_span(def_id).shrink_to_hi()),
),
_ => (String::new(), None),
};
self.cx.emit_spanned_lint(
RPIT_HIDDEN_INFERRED_BOUND,
pred_span,
RpitHiddenInferredBoundLint {
ty,
proj_ty: proj_term,
assoc_pred_span,
suggestion,
suggest_span,
},
);
}
}
}
}

ty.super_visit_with(self)
}
}

#[derive(LintDiagnostic)]
#[diag(lint::rpit_hidden_inferred_bound)]
struct RpitHiddenInferredBoundLint<'tcx> {
ty: Ty<'tcx>,
proj_ty: Ty<'tcx>,
#[label(lint::specifically)]
assoc_pred_span: Span,
#[suggestion_verbose(applicability = "machine-applicable", code = "{suggestion}")]
suggest_span: Option<Span>,
suggestion: String,
}
4 changes: 3 additions & 1 deletion compiler/rustc_middle/src/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,9 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool {
match expn_data.kind {
ExpnKind::Inlined
| ExpnKind::Root
| ExpnKind::Desugaring(DesugaringKind::ForLoop | DesugaringKind::WhileLoop) => false,
| ExpnKind::Desugaring(
DesugaringKind::ForLoop | DesugaringKind::WhileLoop | DesugaringKind::OpaqueTy,
) => false,
ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
ExpnKind::Macro(MacroKind::Bang, _) => {
// Dummy span for the `def_site` means it's an external macro.
Expand Down