The Giallorossi ran out comfortable winners at the San Siro on Saturday, but Napoli's victory over Frosinone means the capital club were unable to overhaul them in second.
Roma were unable to overhaul second-placed Napoli in Serie A despite a comfortable 3-1 victory over AC Milan.
Napoli's 4-0 win against relegated Frosinone prevented Luciano Spalletti's in-form side from pipping them to the runners-up spot behind champions Juventus, while Milan's defeat could cost them a place in Europe next season.
Having failed to climb above Sassuolo into sixth place, Cristian Brocchi's men must now beat Juventus in the Coppa Italia final next weekend if they are to qualify for the Europa League.
Amidst a subdued atmosphere, the hosts struggled to contain a confident Roma side who finish the season in third spot with a brilliant 17-match unbeaten league run.
Mohamed Salah's first-half goal was his 14th of the Serie A season, while efforts from Stephan El Shaarawy and substitute Emerson Palmieri made the game safe for Roma, rendering Carlos Bacca's late reply nothing more than a consolation.
The defeat extended Milan's winless run at home to five games and has surely done little to enhance interim boss Brocchi's prospects of securing the head coach's position for next season.
Roma made a bright start, patiently retaining possession as they probed away at the Milan defence, and came closest to taking an early lead.
An underhit backpass from Alex was seized upon by Salah and the attacker raced through on goal, only to drag his low shot wide.
The Egypt international was not to be denied after 19 minutes, though, with Alex once again the man at fault.
The defender played Salah onside, allowing him to latch on to Kevin Strootman's delightful throughball and calmly fire past Gianluigi Donnarumma.
The visitors continued to look the more likely as the half wore on, with Miralem Pjanic and Alessandro Florenzi both drawing smart stops from Donnarumma and El Shaarawy squandering a great, close-range opportunity.
Milan, meanwhile, rarely threatened before the break, with Roma goalkeeper Wojciech Szczesny forced to make just one regulation save from Keisuke Honda.
Honda was involved again as the hosts began the second half with a little more purpose, blazing over the bar from the edge of the box after the Roma defence had failed to clear its lines.
Milan's own defensive vulnerabilities were exposed again, however, when Florenzi was allowed far too much time and space but could only fire tamely at Donnarumma.
El Shaarawy made amends for his first-half miss just before the hour mark, chesting down a pass from Pjanic before finding the bottom corner and then being applauded by the home fans for refusing to celebrate scoring against his former club.
Francesco Totti came within inches of making it three a few moments later, forcing Donnarumma into a superb save with his first touch after being introduced for his now customary cameo off the bench.
Szczesny was then forced into action to keep out a header from the lively Honda, but it was Roma who continued to threaten and it came as no surprise when they made it 3-0.
Totti found Salah with a clever backheel, his shot was parried by the overworked Donnarumma and Emerson rattled home the rebound to score his first Roma goal.
Bacca did manage to bundle home from close range late on for Brocchi's side, but it was scant consolation for the Milan fans, many of whom had already headed for the exits by the time the Colombia international bagged his 18th league goal of the season.