Skip to content
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
5 changes: 4 additions & 1 deletion crates/hir-def/src/expr_store/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2410,7 +2410,10 @@ impl ExprCollector<'_> {
let start = range_part_lower(p.start());
let end = range_part_lower(p.end());
// FIXME: Exclusive ended pattern range is stabilised
Pat::Range { start, end }
match p.op_kind() {
Some(range_type) => Pat::Range { start, end, range_type },
None => Pat::Missing,
}
}
};
let ptr = AstPtr::new(&pat);
Expand Down
13 changes: 8 additions & 5 deletions crates/hir-def/src/expr_store/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::{
use hir_expand::{Lookup, mod_path::PathKind};
use itertools::Itertools;
use span::Edition;
use syntax::ast::HasName;
use syntax::ast::{HasName, RangeOp};

use crate::{
AdtId, DefWithBodyId, GenericDefId, TypeParamId, VariantId,
Expand Down Expand Up @@ -735,8 +735,8 @@ impl Printer<'_> {
self.print_expr_in(prec, *lhs);
}
match range_type {
ast::RangeOp::Exclusive => w!(self, ".."),
ast::RangeOp::Inclusive => w!(self, "..="),
RangeOp::Exclusive => w!(self, ".."),
RangeOp::Inclusive => w!(self, "..="),
};
if let Some(rhs) = rhs {
self.print_expr_in(prec, *rhs);
Expand Down Expand Up @@ -937,11 +937,14 @@ impl Printer<'_> {
});
w!(self, "}}");
}
Pat::Range { start, end } => {
Pat::Range { start, end, range_type } => {
if let Some(start) = start {
self.print_expr_in(prec, *start);
}
w!(self, "..=");
match range_type {
RangeOp::Inclusive => w!(self, "..="),
RangeOp::Exclusive => w!(self, ".."),
}
if let Some(end) = end {
self.print_expr_in(prec, *end);
}
Expand Down
2 changes: 1 addition & 1 deletion crates/hir-def/src/expr_store/tests/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ const fn f(x: i32) -> i32 {

let MatchArm { pat, .. } = mtch_arms[1];
match body[pat] {
Pat::Range { start, end } => {
Pat::Range { start, end, range_type: _ } => {
let hir_start = &body[start.unwrap()];
let hir_end = &body[end.unwrap()];

Expand Down
1 change: 1 addition & 0 deletions crates/hir-def/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,7 @@ pub enum Pat {
Range {
start: Option<ExprId>,
end: Option<ExprId>,
range_type: RangeOp,
},
Slice {
prefix: Box<[PatId]>,
Expand Down
3 changes: 1 addition & 2 deletions crates/hir-ty/src/infer/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -772,8 +772,7 @@ impl<'db> InferenceContext<'_, 'db> {
Expr::Range { lhs, rhs, range_type } => {
let lhs_ty =
lhs.map(|e| self.infer_expr_inner(e, &Expectation::none(), ExprIsRead::Yes));
let rhs_expect =
lhs_ty.as_ref().map_or_else(Expectation::none, |ty| Expectation::has_type(*ty));
let rhs_expect = lhs_ty.map_or_else(Expectation::none, Expectation::has_type);
let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect, ExprIsRead::Yes));
let single_arg_adt = |adt, ty: Ty<'db>| {
Ty::new_adt(
Expand Down
49 changes: 46 additions & 3 deletions crates/hir-ty/src/infer/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use hir_expand::name::Name;
use rustc_ast_ir::Mutability;
use rustc_type_ir::inherent::{GenericArg as _, GenericArgs as _, IntoKind, SliceLike, Ty as _};
use stdx::TupleExt;
use syntax::ast::RangeOp;

use crate::{
DeclContext, DeclOrigin, InferenceDiagnostic,
Expand Down Expand Up @@ -349,9 +350,51 @@ impl<'db> InferenceContext<'_, 'db> {
self.infer_slice_pat(expected, prefix, *slice, suffix, default_bm, decl)
}
Pat::Wild => expected,
Pat::Range { .. } => {
// FIXME: do some checks here.
expected
Pat::Range { start, end, range_type } => {
// FIXME: Expectation
let lhs_expectation = Expectation::none();
let lhs_ty =
start.map(|start| self.infer_expr(start, &lhs_expectation, ExprIsRead::Yes));
let rhs_expectation = lhs_ty.map_or_else(Expectation::none, Expectation::HasType);
let rhs_ty = end.map(|end| self.infer_expr(end, &rhs_expectation, ExprIsRead::Yes));
let single_arg_adt = |adt, ty: Ty<'db>| {
Ty::new_adt(
self.interner(),
adt,
GenericArgs::new_from_iter(self.interner(), [ty.into()]),
)
};
match (range_type, lhs_ty, rhs_ty) {
(RangeOp::Exclusive, None, None) => match self.resolve_range_full() {
Some(adt) => Ty::new_adt(self.interner(), adt, self.types.empty_args),
None => self.err_ty(),
},
(RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() {
Some(adt) => single_arg_adt(adt, ty),
None => self.err_ty(),
},
(RangeOp::Inclusive, None, Some(ty)) => {
match self.resolve_range_to_inclusive() {
Some(adt) => single_arg_adt(adt, ty),
None => self.err_ty(),
}
}
(RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() {
Some(adt) => single_arg_adt(adt, ty),
None => self.err_ty(),
},
(RangeOp::Inclusive, Some(_), Some(ty)) => {
match self.resolve_range_inclusive() {
Some(adt) => single_arg_adt(adt, ty),
None => self.err_ty(),
}
}
(RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() {
Some(adt) => single_arg_adt(adt, ty),
None => self.err_ty(),
},
(RangeOp::Inclusive, _, None) => self.err_ty(),
}
}
&Pat::Lit(expr) => {
// Don't emit type mismatches again, the expression lowering already did that.
Expand Down
2 changes: 1 addition & 1 deletion crates/hir-ty/src/mir/lower/pattern_matching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ impl<'db> MirLowerCtx<'_, 'db> {
mode,
)?
}
Pat::Range { start, end } => {
Pat::Range { start, end, range_type: _ } => {
let mut add_check = |l: &ExprId, binop| -> Result<'db, ()> {
let lv = self.lower_literal_or_const_to_operand(self.infer[pattern], l)?;
let else_target = *current_else.get_or_insert_with(|| self.new_basic_block());
Expand Down
41 changes: 25 additions & 16 deletions crates/hir-ty/src/tests/patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,24 +189,33 @@ fn infer_literal_pattern() {
fn infer_range_pattern() {
check_infer_with_mismatches(
r#"
fn test(x: &i32) {
if let 1..76 = 2u32 {}
if let 1..=76 = 2u32 {}
}
//- minicore: range
fn test(x..y: &core::ops::Range<u32>) {
if let 1..76 = 2u32 {}
if let 1..=76 = 2u32 {}
}
"#,
expect![[r#"
8..9 'x': &'? i32
17..75 '{ ...2 {} }': ()
23..45 'if let...u32 {}': ()
26..42 'let 1....= 2u32': bool
30..35 '1..76': u32
38..42 '2u32': u32
43..45 '{}': ()
50..73 'if let...u32 {}': ()
53..70 'let 1....= 2u32': bool
57..63 '1..=76': u32
66..70 '2u32': u32
71..73 '{}': ()
8..9 'x': u32
8..12 'x..y': Range<u32>
11..12 'y': u32
38..96 '{ ...2 {} }': ()
44..66 'if let...u32 {}': ()
47..63 'let 1....= 2u32': bool
51..52 '1': i32
51..56 '1..76': Range<i32>
54..56 '76': i32
59..63 '2u32': u32
64..66 '{}': ()
71..94 'if let...u32 {}': ()
74..91 'let 1....= 2u32': bool
78..79 '1': i32
78..84 '1..=76': RangeInclusive<i32>
82..84 '76': i32
87..91 '2u32': u32
92..94 '{}': ()
51..56: expected u32, got Range<i32>
78..84: expected u32, got RangeInclusive<i32>
"#]],
);
}
Expand Down