Skip to content

Commit a66777c

Browse files
committed
Merge branch 'master' into sync-from-rust
2 parents adf052c + 9279c65 commit a66777c

File tree

26 files changed

+738
-379
lines changed

26 files changed

+738
-379
lines changed

crates/hir-def/src/body/lower.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,8 @@ impl ExprCollector<'_> {
622622
ast::Expr::IndexExpr(e) => {
623623
let base = self.collect_expr_opt(e.base());
624624
let index = self.collect_expr_opt(e.index());
625-
self.alloc_expr(Expr::Index { base, index }, syntax_ptr)
625+
let is_assignee_expr = self.is_lowering_assignee_expr;
626+
self.alloc_expr(Expr::Index { base, index, is_assignee_expr }, syntax_ptr)
626627
}
627628
ast::Expr::RangeExpr(e) => {
628629
let lhs = e.start().map(|lhs| self.collect_expr(lhs));

crates/hir-def/src/body/pretty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ impl Printer<'_> {
376376
w!(self, ") ");
377377
}
378378
}
379-
Expr::Index { base, index } => {
379+
Expr::Index { base, index, is_assignee_expr: _ } => {
380380
self.print_expr(*base);
381381
w!(self, "[");
382382
self.print_expr(*index);

crates/hir-def/src/hir.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ pub enum Expr {
265265
Index {
266266
base: ExprId,
267267
index: ExprId,
268+
is_assignee_expr: bool,
268269
},
269270
Closure {
270271
args: Box<[PatId]>,
@@ -432,7 +433,7 @@ impl Expr {
432433
f(rhs);
433434
}
434435
}
435-
Expr::Index { base, index } => {
436+
Expr::Index { base, index, .. } => {
436437
f(*base);
437438
f(*index);
438439
}

crates/hir-expand/src/db.rs

+33-15
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,13 @@ fn parse_macro_expansion(
390390
let expand_to = loc.expand_to();
391391
let mbe::ValueResult { value: tt, err } = macro_expand(db, macro_file.macro_call_id, loc);
392392

393-
let (parse, rev_token_map) = token_tree_to_syntax_node(&tt, expand_to);
393+
let (parse, rev_token_map) = token_tree_to_syntax_node(
394+
match &tt {
395+
CowArc::Arc(it) => it,
396+
CowArc::Owned(it) => it,
397+
},
398+
expand_to,
399+
);
394400

395401
ExpandResult { value: (parse, Arc::new(rev_token_map)), err }
396402
}
@@ -669,15 +675,20 @@ fn macro_expander(db: &dyn ExpandDatabase, id: MacroDefId) -> TokenExpander {
669675
}
670676
}
671677

678+
enum CowArc<T> {
679+
Arc(Arc<T>),
680+
Owned(T),
681+
}
682+
672683
fn macro_expand(
673684
db: &dyn ExpandDatabase,
674685
macro_call_id: MacroCallId,
675686
loc: MacroCallLoc,
676-
) -> ExpandResult<Arc<tt::Subtree>> {
687+
) -> ExpandResult<CowArc<tt::Subtree>> {
677688
let _p = profile::span("macro_expand");
678689

679690
let ExpandResult { value: tt, mut err } = match loc.def.kind {
680-
MacroDefKind::ProcMacro(..) => return db.expand_proc_macro(macro_call_id),
691+
MacroDefKind::ProcMacro(..) => return db.expand_proc_macro(macro_call_id).map(CowArc::Arc),
681692
MacroDefKind::BuiltInDerive(expander, ..) => {
682693
let (root, map) = parse_with_map(db, loc.kind.file_id());
683694
let root = root.syntax_node();
@@ -692,7 +703,7 @@ fn macro_expand(
692703
let ValueResult { value, err } = db.macro_arg(macro_call_id);
693704
let Some((macro_arg, undo_info)) = value else {
694705
return ExpandResult {
695-
value: Arc::new(tt::Subtree {
706+
value: CowArc::Owned(tt::Subtree {
696707
delimiter: tt::Delimiter::invisible_spanned(loc.call_site),
697708
token_trees: Vec::new(),
698709
}),
@@ -718,7 +729,7 @@ fn macro_expand(
718729
// As such we just return the input subtree here.
719730
MacroDefKind::BuiltInEager(..) if loc.eager.is_none() => {
720731
return ExpandResult {
721-
value: macro_arg.clone(),
732+
value: CowArc::Arc(macro_arg.clone()),
722733
err: err.map(|err| {
723734
let mut buf = String::new();
724735
for err in &**err {
@@ -752,12 +763,17 @@ fn macro_expand(
752763
// Skip checking token tree limit for include! macro call
753764
if !loc.def.is_include() {
754765
// Set a hard limit for the expanded tt
755-
if let Err(value) = check_tt_count(&tt, loc.call_site) {
756-
return value;
766+
if let Err(value) = check_tt_count(&tt) {
767+
return value.map(|()| {
768+
CowArc::Owned(tt::Subtree {
769+
delimiter: tt::Delimiter::invisible_spanned(loc.call_site),
770+
token_trees: vec![],
771+
})
772+
});
757773
}
758774
}
759775

760-
ExpandResult { value: Arc::new(tt), err }
776+
ExpandResult { value: CowArc::Owned(tt), err }
761777
}
762778

763779
fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt::Subtree>> {
@@ -796,8 +812,13 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<A
796812
);
797813

798814
// Set a hard limit for the expanded tt
799-
if let Err(value) = check_tt_count(&tt, loc.call_site) {
800-
return value;
815+
if let Err(value) = check_tt_count(&tt) {
816+
return value.map(|()| {
817+
Arc::new(tt::Subtree {
818+
delimiter: tt::Delimiter::invisible_spanned(loc.call_site),
819+
token_trees: vec![],
820+
})
821+
});
801822
}
802823

803824
fixup::reverse_fixups(&mut tt, &undo_info);
@@ -819,14 +840,11 @@ fn token_tree_to_syntax_node(
819840
mbe::token_tree_to_syntax_node(tt, entry_point)
820841
}
821842

822-
fn check_tt_count(tt: &tt::Subtree, call_site: Span) -> Result<(), ExpandResult<Arc<tt::Subtree>>> {
843+
fn check_tt_count(tt: &tt::Subtree) -> Result<(), ExpandResult<()>> {
823844
let count = tt.count();
824845
if TOKEN_LIMIT.check(count).is_err() {
825846
Err(ExpandResult {
826-
value: Arc::new(tt::Subtree {
827-
delimiter: tt::Delimiter::invisible_spanned(call_site),
828-
token_trees: vec![],
829-
}),
847+
value: (),
830848
err: Some(ExpandError::other(format!(
831849
"macro invocation exceeds token limit: produced {} tokens, limit is {}",
832850
count,

crates/hir-expand/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ pub enum MacroCallKind {
220220
},
221221
Attr {
222222
ast_id: AstId<ast::Item>,
223+
// FIXME: This is being interned, subtrees can very quickly differ just slightly causing
224+
// leakage problems here
223225
attr_args: Option<Arc<tt::Subtree>>,
224226
/// Syntactical index of the invoking `#[attribute]`.
225227
///

crates/hir-ty/src/infer/closure.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ impl InferenceContext<'_> {
598598
self.consume_expr(expr);
599599
}
600600
}
601-
Expr::Index { base, index } => {
601+
Expr::Index { base, index, is_assignee_expr: _ } => {
602602
self.select_from_expr(*base);
603603
self.consume_expr(*index);
604604
}

crates/hir-ty/src/infer/expr.rs

+19-6
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,7 @@ impl InferenceContext<'_> {
744744
(RangeOp::Inclusive, _, None) => self.err_ty(),
745745
}
746746
}
747-
Expr::Index { base, index } => {
747+
Expr::Index { base, index, is_assignee_expr } => {
748748
let base_ty = self.infer_expr_inner(*base, &Expectation::none());
749749
let index_ty = self.infer_expr(*index, &Expectation::none());
750750

@@ -772,11 +772,24 @@ impl InferenceContext<'_> {
772772
.build();
773773
self.write_method_resolution(tgt_expr, func, substs);
774774
}
775-
self.resolve_associated_type_with_params(
776-
self_ty,
777-
self.resolve_ops_index_output(),
778-
&[index_ty.cast(Interner)],
779-
)
775+
let assoc = self.resolve_ops_index_output();
776+
let res = self.resolve_associated_type_with_params(
777+
self_ty.clone(),
778+
assoc,
779+
&[index_ty.clone().cast(Interner)],
780+
);
781+
782+
if *is_assignee_expr {
783+
if let Some(index_trait) = self.resolve_lang_trait(LangItem::IndexMut) {
784+
let trait_ref = TyBuilder::trait_ref(self.db, index_trait)
785+
.push(self_ty)
786+
.fill(|_| index_ty.clone().cast(Interner))
787+
.build();
788+
self.push_obligation(trait_ref.cast(Interner));
789+
}
790+
}
791+
792+
res
780793
} else {
781794
self.err_ty()
782795
}

crates/hir-ty/src/infer/mutability.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ impl InferenceContext<'_> {
9696
Expr::RecordLit { path: _, fields, spread, ellipsis: _, is_assignee_expr: _ } => {
9797
self.infer_mut_not_expr_iter(fields.iter().map(|it| it.expr).chain(*spread))
9898
}
99-
&Expr::Index { base, index } => {
99+
&Expr::Index { base, index, is_assignee_expr: _ } => {
100100
if mutability == Mutability::Mut {
101101
if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr) {
102102
if let Some(index_trait) = self

crates/hir-ty/src/mir/lower/as_place.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ impl MirLowerCtx<'_> {
218218
self.push_field_projection(&mut r, expr_id)?;
219219
Ok(Some((r, current)))
220220
}
221-
Expr::Index { base, index } => {
221+
Expr::Index { base, index, is_assignee_expr: _ } => {
222222
let base_ty = self.expr_ty_after_adjustments(*base);
223223
let index_ty = self.expr_ty_after_adjustments(*index);
224224
if index_ty != TyBuilder::usize()

crates/hir-ty/src/tests/traits.rs

+47
Original file line numberDiff line numberDiff line change
@@ -4506,3 +4506,50 @@ fn ttt() {
45064506
"#,
45074507
);
45084508
}
4509+
4510+
#[test]
4511+
fn infer_borrow() {
4512+
check_types(
4513+
r#"
4514+
//- minicore: index
4515+
pub struct SomeMap<K>;
4516+
4517+
pub trait Borrow<Borrowed: ?Sized> {
4518+
fn borrow(&self) -> &Borrowed;
4519+
}
4520+
4521+
impl<T: ?Sized> Borrow<T> for T {
4522+
fn borrow(&self) -> &T {
4523+
self
4524+
}
4525+
}
4526+
4527+
impl<T: ?Sized> Borrow<T> for &T {
4528+
fn borrow(&self) -> &T {
4529+
&**self
4530+
}
4531+
}
4532+
4533+
impl<K, KB: Borrow<K>> core::ops::Index<KB> for SomeMap<K> {
4534+
type Output = ();
4535+
4536+
fn index(&self, _: KB) -> &() {
4537+
&()
4538+
}
4539+
}
4540+
4541+
impl<K> core::ops::IndexMut<K> for SomeMap<K> {
4542+
fn index_mut(&mut self, _: K) -> &mut () {
4543+
&mut ()
4544+
}
4545+
}
4546+
4547+
fn foo() {
4548+
let mut map = SomeMap;
4549+
map["a"] = ();
4550+
map;
4551+
//^^^ SomeMap<&str>
4552+
}
4553+
"#,
4554+
);
4555+
}

0 commit comments

Comments
 (0)