Skip to content

Commit

Permalink
Auto merge of rust-lang#120025 - matthiaskrgr:rollup-e9ai06k, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 8 pull requests

Successful merges:

 - rust-lang#118361 (stabilise bound_map)
 - rust-lang#119816 (Define hidden types in confirmation)
 - rust-lang#119900 (Inline `check_closure`, simplify `deduce_sig_from_projection`)
 - rust-lang#119969 (Simplify `closure_env_ty` and `closure_env_param`)
 - rust-lang#119990 (Add private `NonZero<T>` type alias.)
 - rust-lang#119998 (Update books)
 - rust-lang#120002 (Lint `overlapping_ranges_endpoints` directly instead of collecting into a Vec)
 - rust-lang#120018 (Don't allow `.html` files in `tests/mir-opt/`)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jan 16, 2024
2 parents bf2637f + 9154410 commit e64f849
Show file tree
Hide file tree
Showing 21 changed files with 220 additions and 221 deletions.
6 changes: 5 additions & 1 deletion compiler/rustc_borrowck/src/universal_regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
kind: ty::BrEnv,
};
let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
let closure_ty = tcx.closure_env_ty(def_id, args, env_region).unwrap();
let closure_ty = tcx.closure_env_ty(
Ty::new_closure(tcx, def_id, args),
args.as_closure().kind(),
env_region,
);

// The "inputs" of the closure in the
// signature appear as a tuple. The MIR side
Expand Down
67 changes: 15 additions & 52 deletions compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::GenericArgs;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_span::def_id::LocalDefId;
use rustc_span::{sym, Span};
use rustc_span::Span;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::error_reporting::ArgKind;
Expand Down Expand Up @@ -49,7 +49,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr_span: Span,
expected: Expectation<'tcx>,
) -> Ty<'tcx> {
trace!("decl = {:#?}", closure.fn_decl);
let tcx = self.tcx;
let body = tcx.hir().body(closure.body);
let expr_def_id = closure.def_id;

// It's always helpful for inference if we know the kind of
// closure sooner rather than later, so first examine the expected
Expand All @@ -61,24 +63,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None => (None, None),
};

self.check_closure(closure, expr_span, expected_kind, expected_sig)
}

#[instrument(skip(self, closure), level = "debug", ret)]
fn check_closure(
&self,
closure: &hir::Closure<'tcx>,
expr_span: Span,
opt_kind: Option<ty::ClosureKind>,
expected_sig: Option<ExpectedSig<'tcx>>,
) -> Ty<'tcx> {
let tcx = self.tcx;
let body = tcx.hir().body(closure.body);

trace!("decl = {:#?}", closure.fn_decl);
let expr_def_id = closure.def_id;
debug!(?expr_def_id);

let ClosureSignatures { bound_sig, liberated_sig } =
self.sig_of_closure(expr_def_id, closure.fn_decl, closure.kind, expected_sig);

Expand Down Expand Up @@ -139,9 +123,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
};

let mut fcx = FnCtxt::new(self, self.param_env, closure.def_id);
check_fn(
&mut fcx,
&mut FnCtxt::new(self, self.param_env, closure.def_id),
liberated_sig,
coroutine_types,
closure.fn_decl,
Expand Down Expand Up @@ -174,9 +157,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
)
});

debug!(?sig, ?opt_kind);
debug!(?sig, ?expected_kind);

let closure_kind_ty = match opt_kind {
let closure_kind_ty = match expected_kind {
Some(kind) => Ty::from_closure_kind(tcx, kind),

// Create a type variable (for now) to represent the closure kind.
Expand Down Expand Up @@ -204,11 +187,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let Some(CoroutineTypes { resume_ty, yield_ty }) = coroutine_types else {
bug!("expected coroutine to have yield/resume types");
};
let interior = fcx.next_ty_var(TypeVariableOrigin {
let interior = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: body.value.span,
});
fcx.deferred_coroutine_interiors.borrow_mut().push((
self.deferred_coroutine_interiors.borrow_mut().push((
expr_def_id,
body.id(),
interior,
Expand Down Expand Up @@ -364,36 +347,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let tcx = self.tcx;

let trait_def_id = projection.trait_def_id(tcx);

let is_fn = tcx.is_fn_trait(trait_def_id);

let coroutine_trait = tcx.lang_items().coroutine_trait();
let is_gen = coroutine_trait == Some(trait_def_id);

if !is_fn && !is_gen {
debug!("not fn or coroutine");
// For now, we only do signature deduction based off of the `Fn` traits.
if !tcx.is_fn_trait(trait_def_id) {
return None;
}

// Check that we deduce the signature from the `<_ as std::ops::Coroutine>::Return`
// associated item and not yield.
if is_gen && self.tcx.associated_item(projection.projection_def_id()).name != sym::Return {
debug!("not `Return` assoc item of `Coroutine`");
return None;
}

let input_tys = if is_fn {
let arg_param_ty = projection.skip_binder().projection_ty.args.type_at(1);
let arg_param_ty = self.resolve_vars_if_possible(arg_param_ty);
debug!(?arg_param_ty);
let arg_param_ty = projection.skip_binder().projection_ty.args.type_at(1);
let arg_param_ty = self.resolve_vars_if_possible(arg_param_ty);
debug!(?arg_param_ty);

match arg_param_ty.kind() {
&ty::Tuple(tys) => tys,
_ => return None,
}
} else {
// Coroutines with a `()` resume type may be defined with 0 or 1 explicit arguments,
// else they must have exactly 1 argument. For now though, just give up in this case.
let ty::Tuple(input_tys) = *arg_param_ty.kind() else {
return None;
};

Expand Down
14 changes: 5 additions & 9 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -604,19 +604,15 @@ impl<'tcx> TyCtxt<'tcx> {
/// wrapped in a binder.
pub fn closure_env_ty(
self,
closure_def_id: DefId,
closure_args: GenericArgsRef<'tcx>,
closure_ty: Ty<'tcx>,
closure_kind: ty::ClosureKind,
env_region: ty::Region<'tcx>,
) -> Option<Ty<'tcx>> {
let closure_ty = Ty::new_closure(self, closure_def_id, closure_args);
let closure_kind_ty = closure_args.as_closure().kind_ty();
let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
let env_ty = match closure_kind {
) -> Ty<'tcx> {
match closure_kind {
ty::ClosureKind::Fn => Ty::new_imm_ref(self, env_region, closure_ty),
ty::ClosureKind::FnMut => Ty::new_mut_ref(self, env_region, closure_ty),
ty::ClosureKind::FnOnce => closure_ty,
};
Some(env_ty)
}
}

/// Returns `true` if the node pointed to by `def_id` is a `static` item.
Expand Down
56 changes: 19 additions & 37 deletions compiler/rustc_mir_build/src/thir/cx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,50 +117,32 @@ impl<'tcx> Cx<'tcx> {
pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p)
}

fn closure_env_param(&self, owner_def: LocalDefId, owner_id: HirId) -> Option<Param<'tcx>> {
match self.tcx.def_kind(owner_def) {
DefKind::Closure if self.tcx.is_coroutine(owner_def.to_def_id()) => {
let coroutine_ty = self.typeck_results.node_type(owner_id);
let coroutine_param = Param {
ty: coroutine_ty,
pat: None,
ty_span: None,
self_kind: None,
hir_id: None,
};
Some(coroutine_param)
fn closure_env_param(&self, owner_def: LocalDefId, expr_id: HirId) -> Option<Param<'tcx>> {
if self.tcx.def_kind(owner_def) != DefKind::Closure {
return None;
}

let closure_ty = self.typeck_results.node_type(expr_id);
Some(match *closure_ty.kind() {
ty::Coroutine(..) => {
Param { ty: closure_ty, pat: None, ty_span: None, self_kind: None, hir_id: None }
}
DefKind::Closure => {
let closure_ty = self.typeck_results.node_type(owner_id);

let ty::Closure(closure_def_id, closure_args) = *closure_ty.kind() else {
bug!("closure expr does not have closure type: {:?}", closure_ty);
};

let bound_vars =
self.tcx.mk_bound_variable_kinds(&[ty::BoundVariableKind::Region(ty::BrEnv)]);
let br = ty::BoundRegion {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind: ty::BrEnv,
};
let env_region = ty::Region::new_bound(self.tcx, ty::INNERMOST, br);
let closure_env_ty =
self.tcx.closure_env_ty(closure_def_id, closure_args, env_region).unwrap();
let liberated_closure_env_ty = self.tcx.instantiate_bound_regions_with_erased(
ty::Binder::bind_with_vars(closure_env_ty, bound_vars),
ty::Closure(_, closure_args) => {
let closure_env_ty = self.tcx.closure_env_ty(
closure_ty,
closure_args.as_closure().kind(),
self.tcx.lifetimes.re_erased,
);
let env_param = Param {
ty: liberated_closure_env_ty,
Param {
ty: closure_env_ty,
pat: None,
ty_span: None,
self_kind: None,
hir_id: None,
};

Some(env_param)
}
}
_ => None,
}
_ => bug!("unexpected closure type: {closure_ty}"),
})
}

fn explicit_params<'a>(
Expand Down
25 changes: 14 additions & 11 deletions compiler/rustc_pattern_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,9 @@ use rustc_middle::ty::Ty;
#[cfg(feature = "rustc")]
use rustc_span::ErrorGuaranteed;

use crate::constructor::{Constructor, ConstructorSet};
use crate::constructor::{Constructor, ConstructorSet, IntRange};
#[cfg(feature = "rustc")]
use crate::lints::{
lint_nonexhaustive_missing_variants, lint_overlapping_range_endpoints, PatternColumn,
};
use crate::lints::{lint_nonexhaustive_missing_variants, PatternColumn};
use crate::pat::DeconstructedPat;
#[cfg(feature = "rustc")]
use crate::rustc::RustcMatchCheckCtxt;
Expand Down Expand Up @@ -77,6 +75,17 @@ pub trait TypeCx: Sized + fmt::Debug {

/// Raise a bug.
fn bug(&self, fmt: fmt::Arguments<'_>) -> !;

/// Lint that the range `pat` overlapped with all the ranges in `overlaps_with`, where the range
/// they overlapped over is `overlaps_on`. We only detect singleton overlaps.
/// The default implementation does nothing.
fn lint_overlapping_range_endpoints(
&self,
_pat: &DeconstructedPat<'_, Self>,
_overlaps_on: IntRange,
_overlaps_with: &[&DeconstructedPat<'_, Self>],
) {
}
}

/// Context that provides information global to a match.
Expand Down Expand Up @@ -111,16 +120,10 @@ pub fn analyze_match<'p, 'tcx>(

let report = compute_match_usefulness(cx, arms, scrut_ty, scrut_validity)?;

let pat_column = PatternColumn::new(arms);

// Lint ranges that overlap on their endpoints, which is likely a mistake.
if !report.overlapping_range_endpoints.is_empty() {
lint_overlapping_range_endpoints(cx, &report.overlapping_range_endpoints);
}

// Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting
// `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() {
let pat_column = PatternColumn::new(arms);
lint_nonexhaustive_missing_variants(cx, arms, &pat_column, scrut_ty)?;
}

Expand Down
32 changes: 3 additions & 29 deletions compiler/rustc_pattern_analysis/src/lints.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
use rustc_session::lint;
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
use rustc_span::ErrorGuaranteed;

use crate::errors::{
self, NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered,
};
use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered};
use crate::pat::PatOrWild;
use crate::rustc::{
self, Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RevealedTy,
RustcMatchCheckCtxt, SplitConstructorSet, WitnessPat,
Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RevealedTy, RustcMatchCheckCtxt,
SplitConstructorSet, WitnessPat,
};

/// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that
Expand Down Expand Up @@ -196,26 +193,3 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
}
Ok(())
}

pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>(
cx: MatchCtxt<'a, 'p, 'tcx>,
overlapping_range_endpoints: &[rustc::OverlappingRanges<'p, 'tcx>],
) {
let rcx = cx.tycx;
for overlap in overlapping_range_endpoints {
let overlap_as_pat = rcx.hoist_pat_range(&overlap.overlaps_on, overlap.pat.ty());
let overlaps: Vec<_> = overlap
.overlaps_with
.iter()
.map(|pat| pat.data().unwrap().span)
.map(|span| errors::Overlap { range: overlap_as_pat.clone(), span })
.collect();
let pat_span = overlap.pat.data().unwrap().span;
rcx.tcx.emit_spanned_lint(
lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
rcx.match_lint_level,
pat_span,
errors::OverlappingRangeEndpoints { overlap: overlaps, range: pat_span },
);
}
}
37 changes: 27 additions & 10 deletions compiler/rustc_pattern_analysis/src/rustc.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
use smallvec::SmallVec;
use std::fmt;
use std::iter::once;

use rustc_arena::{DroplessArena, TypedArena};
use rustc_data_structures::captures::Captures;
use rustc_hir::def_id::DefId;
use rustc_hir::HirId;
use rustc_index::Idx;
use rustc_index::IndexVec;
use rustc_index::{Idx, IndexVec};
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::{self, Const};
use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange, PatRangeBoundary};
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::ty::TypeVisitableExt;
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, VariantDef};
use rustc_span::ErrorGuaranteed;
use rustc_span::{Span, DUMMY_SP};
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeVisitableExt, VariantDef};
use rustc_session::lint;
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT};
use smallvec::SmallVec;

use crate::constructor::{
IntRange, MaybeInfiniteInt, OpaqueId, RangeEnd, Slice, SliceKind, VariantVisibility,
};
use crate::TypeCx;
use crate::{errors, TypeCx};

use crate::constructor::Constructor::*;

Expand All @@ -34,8 +32,6 @@ pub type DeconstructedPat<'p, 'tcx> =
crate::pat::DeconstructedPat<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
pub type MatchCtxt<'a, 'p, 'tcx> = crate::MatchCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>;
pub type OverlappingRanges<'p, 'tcx> =
crate::usefulness::OverlappingRanges<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
pub(crate) type PlaceCtxt<'a, 'p, 'tcx> =
crate::usefulness::PlaceCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>;
pub(crate) type SplitConstructorSet<'p, 'tcx> =
Expand Down Expand Up @@ -991,6 +987,27 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
fn bug(&self, fmt: fmt::Arguments<'_>) -> ! {
span_bug!(self.scrut_span, "{}", fmt)
}

fn lint_overlapping_range_endpoints(
&self,
pat: &crate::pat::DeconstructedPat<'_, Self>,
overlaps_on: IntRange,
overlaps_with: &[&crate::pat::DeconstructedPat<'_, Self>],
) {
let overlap_as_pat = self.hoist_pat_range(&overlaps_on, pat.ty());
let overlaps: Vec<_> = overlaps_with
.iter()
.map(|pat| pat.data().unwrap().span)
.map(|span| errors::Overlap { range: overlap_as_pat.clone(), span })
.collect();
let pat_span = pat.data().unwrap().span;
self.tcx.emit_spanned_lint(
lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
self.match_lint_level,
pat_span,
errors::OverlappingRangeEndpoints { overlap: overlaps, range: pat_span },
);
}
}

/// Recursively expand this pattern into its subpatterns. Only useful for or-patterns.
Expand Down
Loading

0 comments on commit e64f849

Please sign in to comment.