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 8 pull requests #120025

Merged
merged 20 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
a43dc2b
stabilise bound_map
Dylan-DPC Nov 27, 2023
08fc5e8
Define hidden types in confirmation
oli-obk Jan 10, 2024
0ae0044
Make sure the new solver agrees
oli-obk Jan 10, 2024
50e1580
Inline check_closure
compiler-errors Jan 12, 2024
6a63183
Signature deduction is only done for Fn traits
compiler-errors Jan 12, 2024
6f98a6c
Simplify closure_env_ty and closure_env_param
compiler-errors Jan 14, 2024
f760223
Add private `NonZero<T>` type alias.
reitermarkus Jan 15, 2024
0a049cb
Update books
rustbot Jan 15, 2024
8b66f49
Lint overlapping ranges directly from exhaustiveness
Nadrieril Jan 15, 2024
448c4a4
Remove the unused `overlapping_range_endpoints` Vec
Nadrieril Jan 15, 2024
604d208
Revert unrelated changes from PR 119990
dtolnay Jan 15, 2024
40166c8
Don't allow `.html` files in `tests/mir-opt/`
Zalathar Jan 16, 2024
304a17a
Rollup merge of #118361 - Dylan-DPC:80626/stab/bound-map, r=Amanieu
matthiaskrgr Jan 16, 2024
d4b276c
Rollup merge of #119816 - oli-obk:tait_ice_unify_obligations, r=lcnr
matthiaskrgr Jan 16, 2024
5f9d1d4
Rollup merge of #119900 - compiler-errors:closure-checking, r=oli-obk
matthiaskrgr Jan 16, 2024
4735171
Rollup merge of #119969 - compiler-errors:simplify-closure-env-ty, r=…
matthiaskrgr Jan 16, 2024
ac3108f
Rollup merge of #119990 - reitermarkus:nonzero-type-alias, r=dtolnay
matthiaskrgr Jan 16, 2024
bcea676
Rollup merge of #119998 - rustbot:docs-update, r=ehuss
matthiaskrgr Jan 16, 2024
1f0daa5
Rollup merge of #120002 - Nadrieril:dont-collect, r=compiler-errors
matthiaskrgr Jan 16, 2024
9154410
Rollup merge of #120018 - Zalathar:mir-opt-html, r=Nilstrieb
matthiaskrgr Jan 16, 2024
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
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
Loading