compiler: Retain immutable standalone method metadata

6895879fcbdd55844fb71b504781410e22ce59c567f401cd68fa8226a254f269
Alexis Sellier committed ago 1 parent 84c0637c
lib/std/lang/lower.rad +2 -3
1284 1284
) -> ?*unsafe il::Fn throws (LowerError) where 'arena: 'phase {
1285 1285
    let sym = resolver::symbolFor(self.resolver, node)
1286 1286
        else throw LowerError::MissingSymbol(node);
1287 1287
    let case ast::NodeValue::Ident(mName) = name.value
1288 1288
        else throw LowerError::ExpectedIdentifier;
1289 -
    let me = resolver::findMethodBySymbol(self.resolver, sym)
1289 +
    let me = resolver::findMethodBySymbol(self.resolver, sym.id)
1290 1290
        else throw LowerError::MissingMetadata;
1291 1291
    let qualName = instanceMethodName(self, nil, me.concreteTypeName, mName);
1292 1292
1293 1293
    return try lowerMethod(self, node, qualName, receiverName, sig, body, functionArena);
1294 1294
}
7171 7171
    // Get the receiver as a pointer.
7172 7172
    let parentTy = try typeOf(self, access.parent);
7173 7173
    let receiverVal = try lowerReceiver(self, access.parent, parentTy);
7174 7174
7175 7175
    let qualName = instanceMethodName(self.low, nil, method.concreteTypeName, method.name);
7176 -
    let case resolver::SymbolData::Value { type: resolver::Type::Fn(fnInfo), .. } = method.symbol.data
7177 -
        else panic "lowerMethodCall: expected Fn type on method symbol";
7176 +
    let fnInfo = method.fullFnType;
7178 7177
7179 7178
    // Build args: optional return param slot + receiver + user args.
7180 7179
    let argOffset: u32 = 1 if requiresReturnParam(fnInfo) else 0;
7181 7180
    let args = try allocVals(self, call.args.len + 1 + argOffset);
7182 7181
    set args[argOffset] = receiverVal;
lib/std/lang/resolver.rad +12 -8
108 108
    fnType: *FnType,
109 109
    /// Whether the receiver is mutable.
110 110
    mutable: bool,
111 111
    /// Pointer-like class used by the receiver.
112 112
    receiverClass: types::PointerClass,
113 -
    /// Symbol for the method.
114 -
    symbol: *unsafe mut Symbol,
113 +
    /// Resolver-local identity of the method symbol.
114 +
    symbolId: u32,
115 +
    /// Function type including the receiver, used for emitted calls.
116 +
    fullFnType: *FnType,
115 117
}
116 118
117 119
/// Identifier for the synthetic `len` field.
118 120
export constant LEN_FIELD: *[u8] = "len";
119 121
/// Identifier for the synthetic `ptr` field.
5484 5486
        paramTypes: &paramTypes[..],
5485 5487
        returnType: retTypePtr,
5486 5488
        throwList,
5487 5489
        isUnsafe,
5488 5490
    };
5489 -
    let fnTy = Type::Fn(allocFnType(self, fullFnType));
5491 +
    let fullFnInfo = allocFnType(self, fullFnType);
5492 +
    let fnTy = Type::Fn(fullFnInfo);
5490 5493
5491 5494
    // Function type excluding receiver, for call arg checking.
5492 5495
    let checkFnType = FnType {
5493 5496
        regions: self.regionScope,
5494 5497
        paramTypes: &paramTypes[1..],
5515 5518
        concreteTypeName: typeName,
5516 5519
        name: methodName,
5517 5520
        fnType: allocFnType(self, checkFnType),
5518 5521
        mutable: receiverMut,
5519 5522
        receiverClass,
5520 -
        symbol: sym,
5523 +
        symbolId: sym.id,
5524 +
        fullFnType: fullFnInfo,
5521 5525
    };
5522 5526
    set self.methodsLen += 1;
5523 5527
}
5524 5528
5525 5529
/// Look up an instance entry by trait and concrete type.
5542 5546
        }
5543 5547
    }
5544 5548
    return nil;
5545 5549
}
5546 5550
5547 -
/// Look up a standalone method entry by its symbol.
5548 -
export unsafe fn findMethodBySymbol 'arena (self: &Resolver 'arena, sym: *unsafe mut Symbol) -> ?*unsafe MethodEntry {
5551 +
/// Look up standalone method metadata by its resolver-local symbol identity.
5552 +
export fn findMethodBySymbol 'arena (self: &Resolver 'arena, symbolId: u32) -> ?MethodEntry {
5549 5553
    for i in 0..self.methodsLen {
5550 -
        let entry: *unsafe MethodEntry = &self.methods[i];
5551 -
        if entry.symbol == sym {
5554 +
        let entry = self.methods[i];
5555 +
        if entry.symbolId == symbolId {
5552 5556
            return entry;
5553 5557
        }
5554 5558
    }
5555 5559
    return nil;
5556 5560
}
lib/std/lang/resolver/tests/regions.rad +24 -0
49 49
        assert last.mutable;
50 50
        assert resolver::findTraitMethod(&info.methods[..], "missing") == nil;
51 51
    }
52 52
}
53 53
54 +
/// Standalone method identities select independent registry entries.
55 +
@test unsafe fn testStandaloneMethodIdentityLookup() throws (testing::TestError) {
56 +
    let mut arena = super::testArena();
57 +
    let storage: 'test = &mut arena in {
58 +
        let mut res = super::testResolver(storage);
59 +
        let result = try super::resolveProgramStr(&mut res, "record R {} fn (r: &R) first() {} fn (r: &mut R) second() {}");
60 +
        try super::expectNoErrors(&result);
61 +
        let case ast::NodeValue::Block(block) = result.root.value else throw testing::TestError::Failed;
62 +
        let firstSymbol = resolver::symbolFor(&res, block.statements[1]) else throw testing::TestError::Failed;
63 +
        let lastSymbol = resolver::symbolFor(&res, block.statements[2]) else throw testing::TestError::Failed;
64 +
        let first = resolver::findMethodBySymbol(&res, firstSymbol.id) else throw testing::TestError::Failed;
65 +
        let last = resolver::findMethodBySymbol(&res, lastSymbol.id) else throw testing::TestError::Failed;
66 +
        assert mem::eq(first.name, "first");
67 +
        assert not first.mutable;
68 +
        assert mem::eq(last.name, "second");
69 +
        assert last.mutable;
70 +
        assert first.fullFnType.paramTypes.len == 1;
71 +
        assert first.fnType.paramTypes.len == 0;
72 +
        assert last.fullFnType.paramTypes.len == 1;
73 +
        assert last.fnType.paramTypes.len == 0;
74 +
        assert resolver::findMethodBySymbol(&res, res.symbolCount) == nil;
75 +
    }
76 +
}
77 +
54 78
/// Iteration over raw slices requires permission to read their storage.
55 79
@test unsafe fn testRawSliceIterationRequiresUnsafe() throws (testing::TestError) {
56 80
    for program in [
57 81
        "fn f(p: *unsafe [u32]) { for item in p { assert item == 0; } }",
58 82
        "fn f(p: *unsafe mut [u32]) { for item, index in p { assert item == index; } }",